2012-01-11 12 views
48

文字列としてパスを渡すことで、対象物からの深い値を取得します:
Accessing nested JavaScript objects with string keyJavascriptを:可能性の重複

たぶんタイトルが十分に明確ではないが、私はどのように知りませんでした私が探しているものを指定するために、私の英語は本当に悪いです、申し訳ありません。

オブジェクト値を返す関数を作成しようとしていますが、ネストされたオブジェクトでもうまくいきます。たとえば:

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

私は、関数に文字列「foo.bar」を補給することにより、obj.foo.barの値にアクセスしたいです。

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

ありがとうございます!

+0

を参照してください

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

再帰バージョンです。 https://lodash.com/docs#get –

+0

を参照してください。この質問は重複しているとマークされているため、私はコメントで答える必要があります。 ECMAScript6 Destructuringを使うことができます: 'var obj = {foo:{bar: 'baz'}};({foo:{bar:value}} = obj); console.log(value);' – Alexander

答えて

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とqiao:パスの一部が ' 「ヌル」。これは、あなたの視点に応じて、機能またはバグになる可能性があります。 :-) –

3

文字列をドットに分割してから、繰り返しオブジェクトにインデックスを付けることができます。線に沿って:(obj.foo)リテラルを使用して点線の構文がありますし、使用して構文が括弧で囲まれています:あなたはいくつかの異なる方法で、オブジェクトのプロパティにアクセスすることができますので、作品

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"])。後者の場合、文字列は任意の式の結果である可能性があります。文字列リテラルである必要はありません。

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')'のような関数呼び出しを必要とするとは思わないかもしれませんか?それは現在の質問の範囲外かもしれません... –

+1

@DavidHedlund:フェアポイント、JavaScriptの独自の構文と完全に互換性を持たせるために、各 'part'内の括弧で括られた形式をチェックすると便利かもしれません。私はOPのための練習としてそれを残します。 :-) –

+0

(まあ、完全に*ではありませんが、あなたは基本的に[または-shudder- use] 'eval'を再作成しなければなりません)。 –

5

何かのように:すべての中では、rvが同じ値に設定されている

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

http://meta.stackexchange.com/a/118023/134069 –

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; 
}; 

ここはプロです/デモ:jsfiddle.net/tadeck/5Pt2q/13/

編集:私は冗長な変数を削除し、コードを短縮しました。

+1

美しい。重複しているものよりも優れています。http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key –

+0

配列のサポートが拡張されました。 http://jsfiddle.net/5Pt2q/20/ –

+3

@SteveBlackより良い方法は?より制限された構文をサポートしており、存在しないキーの解決を試行した場合のエラーチェックはありません。 – Alnitak

7

このような意味ですか?これは、これは今_.get(OBJ、プロパティ)を使用してlodashによってサポートされていhttp://jsfiddle.net/kExSr/

+0

ゴールド!これを使ってパス/ Root [1]/This /をオブジェクト{"Root [1]":This {worked: "value"}}にマップしました。 /と変更をリードするトリミングしなければならなかった。それ以外は美しい。 –

+1

これはあまりにも速く見えません。パスを再度join()しないでください。pathが文字列か配列かをチェックしてください – Jonathan