2012-02-17 74 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