2012-02-17 40 views
1

假设我有一个字符串表示对象中的键。这里有一个例子:使用字符串作为键的对象设置值

var obj = { 
    test: 12, 
    high: { 
     sky: { 
     val: 14 
     } 
    }, 
    low: [1, 2, 3] 
}, 
keys = 'high.sky.val'; 

所以,我想设置的obj.high.sky.val值(与'high.sky.val'在一个字符为)。

我知道如何阅读的价值(虽然这未必是最好的方式):

var keyPieces = keys.split('.'), value = obj; 
keyPieces.forEach(function(x){ 
    value = value[x]; 
}); 
console.log(value); // 14 

我无法弄清楚如何设置obj.high.sky.val(不使用eval)。

如何设置属性的值,如果该键是一个字符串?

回答

6

只是为了好玩:

function setKey(key, value, targetObject) { 
    var keys = key.split('.'), obj = targetObject || window, keyPart; 
    while ((keyPart = keys.shift()) && keys.length) { 
    obj = obj[keyPart]; 
    } 
    obj[keyPart] = value; 
} 

编辑:以前的版本也不会与 “无点” 键...固定的工作。

+0

我如何告诉它什么对象使用? – 2012-02-17 23:08:13

+0

挂起,编辑。我假设你想从全局对象开始解决......现在你去了,现在它可以有一个目标对象(否则它默认为'window')。如果你不想'window'默认,只需删除“|| window”。 – 2012-02-17 23:11:24

+0

@火箭,为简单起见编辑了一下。 – 2012-02-17 23:19:03

2
function setDeep(el, key, value) { 
    key = key.split('.'); 
    var i = 0, n = key.length; 
    for (; i < n-1; ++i) { 
     el = el[key[i]]; 
    } 
    return el[key[i]] = value; 
} 

function getDeep(el, key) { 
    key = key.split('.'); 
    var i = 0, n = key.length; 
    for (; i < n; ++i) { 
     el = el[key[i]]; 
    } 
    return el; 
} 

,你可以这样使用它:

setDeep(obj, 'high.sky.val', newValue); 
+2

不应该是'el [key [i]]'? – 2012-02-17 22:18:08

+0

根据@ Kolink的回答,您需要在设置时停止在第二个到最后一个属性,这样'el'是一个对象,而不是一个int。另外,获取时,您需要使用'el [key [i]]'。 – 2012-02-17 22:28:11

+0

@火箭,谢谢你的编辑。 – 2012-02-17 23:20:22

5

其实我不得不做出几个功能GameMaker工作时实现这一目的:HTML5

function js_get(varname) { 
    if(varname.indexOf(".") < 0) 
     return window[varname]; 
    else { 
     var curr = window, steps = varname.split("."), next; 
     while(next = steps.shift()) curr = curr[next]; 
     return curr; 
    } 
} 
function js_set(varname,value) { 
    if(varname.indexOf(".") < 0) 
     window[varname] = value; 
    else { 
     var curr = window, steps = varname.split("."), next, last = steps.pop(); 
     while(next = steps.shift()) curr = curr[next]; 
     curr[last] = value; 
    } 
} 

这工作,因为对象在JS中通过引用传递。

+0

在我的代码中,我尝试了'value = 1000;',它没有更新值。我想我需要停在第二个到最后一个对象,然后设置值。为什么'价值= 1000'工作? – 2012-02-17 22:20:27

+0

这就是这段代码所做的,用'last = steps.pop()'。我只是双重检查它,它确实有效。另一个测试:'a = {b:{c:1}}; d = a.b; d.c = 2;警报(A.B.C); //警报2,而不是1' – 2012-02-17 22:21:46

+0

奇怪。 'a = {b:{c:1}}; d = a.b.c; d = 2;警报(a.b.c);警报1.不知道为什么。我猜是因为'd'被设置为一个值(int),而不是一个对象。这是有道理的。 – 2012-02-17 22:22:52

1

您可以使用一对函数来设置和获取值。我只是举了一个例子。

objGet需要一个对象和密钥字符串。它会尝试获得价值。如果它找不到它,它将返回undefined。

objSet需要一个对象,键字符串和值。它会尝试查找和设置值。如果它不能(因为一个错误的键字符串)它将返回undefined。否则它返回传递的值。

function objGet(obj, keyString) { 
    for(var keys = keyString.split('.'), i = 0, l = keys.length; i < l; i++) { 
     obj = obj[keys[i]]; 
     if(obj === undefined) return undefined; 
    } 
    return obj; 
} 

function objSet(obj, keyString, val) { 
    for(var keys = keyString.split('.'), i = 0, l = keys.length; i < l - 1; i++) { 
     obj = obj[keys[i]]; 
     if(obj === undefined) return undefined; 
    } 
    if(obj[keys[l - 1]] === undefined) return undefined; 
    obj[keys[l - 1]] = val; 
    return val; 
} 


//// TESTING 

var obj = { 
    test: 12, 
    high: { 
     sky: { 
      val: 14 
     } 
    }, 
    low: [1, 2, 3] 
}; 

objGet(obj, 'test'); // returns 12 
objGet(obj, 'high.sky.val'); // returns 14 
objGet(obj, 'high.sky.non.existant'); // returns undefined 

objSet(obj, 'test', 999); // return 999 
obj.test; // 999 

objSet(obj, 'high.sky.non.existant', 1234); // returns undefined 
obj.high.sky; // { val: 14 } 

objSet(obj, 'high.sky.val', 111); // returns 111 
obj.high.sky; // { val: 111 } 
+0

很酷,这个工程:-) – 2012-02-17 22:30:31