可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This question already has an answer here:
-
Convert JavaScript string in dot notation into an object reference
24 answers
Consider this object in javascript,
var obj = { a : { b: 1, c: 2 } };
given the string \"obj.a.b\" how can I get the object this refers to, so that I may alter its value? i.e. I want to be able to do something like
obj.a.b = 5;
obj.a.c = 10;
where \"obj.a.b\" & \"obj.a.c\" are strings (not obj references).
I came across this post where I can get the value the dot notation string is referring to obj but what I need is a way I can get at the object itself?
The nesting of the object may be even deeper than this. i.e. maybe
var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
回答1:
To obtain the value, consider:
function ref(obj, str) {
str = str.split(\".\");
for (var i = 0; i < str.length; i++)
obj = obj[str[i]];
return obj;
}
var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
str = \'a.c.d\'
ref(obj, str) // 3
or in a more fancy way, using reduce:
function ref(obj, str) {
return str.split(\".\").reduce(function(o, x) { return o[x] }, obj);
}
Returning an assignable reference to an object member is not possible in javascript, you\'ll have to use a function like the following:
function set(obj, str, val) {
str = str.split(\".\");
while (str.length > 1)
obj = obj[str.shift()];
return obj[str.shift()] = val;
}
var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
str = \'a.c.d\'
set(obj, str, 99)
console.log(obj.a.c.d) // 99
or use ref
given above to obtain the reference to the containing object and then apply the []
operator to it:
parts = str.split(/\\.(?=[^.]+$)/) // Split \"foo.bar.baz\" into [\"foo.bar\", \"baz\"]
ref(obj, parts[0])[parts[1]] = 99
回答2:
Similar to thg435\'s answer, but with argument checks and supports nest levels where one of the ancestor levels isn\'t yet defined or isn\'t an object.
setObjByString = function(obj, str, val) {
var keys, key;
//make sure str is a string with length
if (!str || !str.length || Object.prototype.toString.call(str) !== \"[object String]\") {
return false;
}
if (obj !== Object(obj)) {
//if it\'s not an object, make it one
obj = {};
}
keys = str.split(\".\");
while (keys.length > 1) {
key = keys.shift();
if (obj !== Object(obj)) {
//if it\'s not an object, make it one
obj = {};
}
if (!(key in obj)) {
//if obj doesn\'t contain the key, add it and set it to an empty object
obj[key] = {};
}
obj = obj[key];
}
return obj[keys[0]] = val;
};
Usage:
var obj;
setObjByString(obj, \"a.b.c.d.e.f\", \"hello\");
回答3:
If this javascript
runs in a browser then you can access the object like this:
window[\'obj\'][\'a\'][\'b\'] = 5
So given the string \"obj.a.b\"
you have to split the it by .
:
var s = \"obj.a.b\"
var e = s.split(\".\")
window[e[0]][e[1]][e[2]] = 5
回答4:
Below is a simple class wrapper around dict
:
class Dots(dict):
def __init__(self, *args, **kargs):
super(Dots, self).__init__(*args, **kargs)
def __getitem__(self, key):
try:
item = super(Dots, self).__getitem__(key)
except KeyError:
item = Dots()
self.__setitem__(key, item)
return Dots(item) if type(item) == dict else item
def __setitem__(self, key, value):
if type(value) == dict: value = Dots(value)
super(Dots, self).__setitem__(key, value)
__getattr__ = __getitem__
__setattr__ = __setitem__
Example:
>>> a = Dots()
>>> a.b.c = 123
>>> a.b.c
123
>>> a.b
{\'c\': 123}
>>> a
{\'b\': {\'c\': 123}}
Missing key are created on the fly as empty Dots()
:
>>> if a.Missing: print \"Exists\"
...
>>> a
{\'Missing\': {}, \'b\': {\'c\': 123}}
回答5:
var obj = { a : { b: 1, c: 2 } };
walkObject(obj,\"a.b\"); // 1
function walkObject( obj, path ){
var parts = path.split(\".\"), i=0, part;
while (obj && (part=parts[i++])) obj=obj[part];
return obj;
}
Or if you like your code terse:
function walkObject( o, path ){
for (var a,p=path.split(\'.\'),i=0; o&&(a=p[i++]); o=o[a]);
return o;
}
回答6:
Returning an assignable reference to an object member is not possible in javascript. You can assign value to a deep object member by dot notation with a single line of code like this.
new Function(\'_\', \'val\', \'_.\' + path + \' = val\')(obj, value);
In you case:
var obj = { a : { b: 1, c: 2 } };
new Function(\'_\', \'val\', \'_.a.b\' + \' = val\')(obj, 5); // Now obj.a.b will be equal to 5