2012-01-11 75 views
48

可能重複獲取從對象的深度價值:
Accessing nested JavaScript objects with string key的Javascript:通過傳遞路徑,它作爲字符串

也許標題是不夠清楚,我只是不知道如何指定我在找什麼,我的英語真的很糟糕,對不起。

我想創建返回對象值的函數,但也與嵌套對象很好玩。例如:

var obj = { 
    foo: { bar: 'baz' } 
}; 

我想suppling字符串「foo.bar」的功能來訪問obj.foo.bar的價值。

function(obj, path) { 
    // Path can be "foo.bar", or just "foo". 
} 

謝謝!

+0

這是現在lodash使用_.get(OBJ,財產)的支持。請參閱https://lodash.com/docs#get – 2017-08-22 10:21:37

+0

由於此問題被標記爲重複(即使不是),我必須在評論中回答。可以使用ECMAScript6解構:'VAR OBJ = {FOO:{欄: '巴茲'}};({FOO:{欄:值}} = OBJ);執行console.log(值);' – Alexander 2018-02-21 14:45:38

回答

37

考慮一下:

var obj = { 
    foo: { bar: 'baz' } 
}; 

function deepFind(obj, path) { 
    var paths = path.split('.') 
    , current = obj 
    , i; 

    for (i = 0; i < paths.length; ++i) { 
    if (current[paths[i]] == undefined) { 
     return undefined; 
    } else { 
     current = current[paths[i]]; 
    } 
    } 
    return current; 
} 

console.log(deepFind(obj, 'foo.bar')) 
+5

@ 7elephant and qiao:失敗(拋出錯誤)如果路徑的任何部分評估爲「 null'。這可能是一個功能或bug,取決於你的觀點。 :-) – 2012-01-11 10:47:39

3

你想分割點上的字符串,然後重複索引到對象,例如,沿着線:

function goDeep(obj, path) { 
    var parts = path.split('.'), 
     rv, 
     index; 
    for (rv = obj, index = 0; rv && index < parts.length; ++index) { 
     rv = rv[parts[index]]; 
    } 
    return rv; 
} 

Live example

這工作,因爲你可以在幾個不同的方式訪問對象的屬性:有使用文字(obj.foo)點語法,而且也用括號語法一個字符串(obj["foo"])。在後一種情況下,字符串可以是任何表達式的結果,它不一定是字符串文字。在所有的,rv被設置爲相同的值:

rv = obj.foo.bar; 
// Or 
rv = obj.foo["bar"]; 
// Or 
f = "foo"; 
rv = obj[f].bar; 
// Or 
s = "b"; 
rv = obj.foo[s + "ar"]; 
+1

當然,所述的要求是沒有表達,但我們可能不會懷疑OP可能同樣想要一個函數調用,比如'goDeep(myObj,'bar [3] .baz')'?這可能是超出範圍對於當前的問題... – 2012-01-11 10:09:27

+1

@DavidHedlund:公平點,它很可能是爲了與JavaScript的自己的語法完全兼容各'part'內檢查括號內的形式是有好處的。我將把它作爲OP的練習。 :-) – 2012-01-11 10:11:20

+0

(好吧,不是*完全*,因爲這樣做你必須基本上重新發明[或-shudder-use]'eval'。但是,大多數情況下兼容)。 – 2012-01-11 10:38:47

5

類似:

function(obj, path) { 
    var current=obj; 
    path.split('.').forEach(function(p){ current = current[p]; }); 
    return current; 
} 
+0

http://meta.stackexchange.com/a/118023/134069 – 2012-01-11 10:11:48

58

這正常工作:

var deep_value = function(obj, path){ 
    for (var i=0, path=path.split('.'), len=path.length; i<len; i++){ 
     obj = obj[path[i]]; 
    }; 
    return obj; 
}; 

這是pro/demo:jsfiddle.net/tadeck/5Pt2q/13/

編輯:我已經刪除了多餘的變量,縮短了代碼。

+1

美麗。比爲了陣列支持而擴展的重複http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key – 2013-03-20 02:10:34

+0

更好。 http://jsfiddle.net/5Pt2q/20/ – 2013-07-30 04:02:23

+3

@SteveBlack更好?它支持更受限制的語法,並且沒有嘗試解析不存在的鍵的錯誤檢查。 – Alnitak 2013-08-06 08:16:48

7

你的意思是這樣的嗎?這是一個遞歸版本

function recLookup(obj, path) { 
    parts = path.split("."); 
    if (parts.length==1){ 
     return obj[parts[0]]; 
    } 
    return recLookup(obj[parts[0]], parts.slice(1).join(".")); 
} 

http://jsfiddle.net/kExSr/

+0

黃金!我能夠使用它來映射路徑/ Root [1]/This/working to object {「Root [1]」:This {worked:「value」}}。不得不削減領先/和改變。到/但否則美麗。 – 2013-03-20 02:05:03

+1

這看起來不太快。不應再次加入()路徑,只要檢查路徑是字符串還是數組 – Jonathan 2016-02-13 16:58:22