変数を使用して動的にオブジェクトプロパティにアクセスする


722

動的な名前を使用してオブジェクトのプロパティにアクセスしようとしています。これは可能ですか?

const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"

回答:


959

オブジェクトのプロパティにアクセスするに2つの方法があります。

  • ドット表記: something.bar
  • ブラケット表記: something['bar']

大括弧の間の値は任意の式にすることができます。したがって、プロパティ名が変数に格納されている場合は、ブラケット表記を使用する必要があります。

var foo = 'bar';
something[foo];
// both x = something[foo] and something[foo] = x work as expected

34
これに注意してください:javascriptコンパイラは文字列の名前を変更しないため、ここでエラーになりますが、オブジェクトのプロパティの名前は変更します
chacham15

6
これが可能である理由の詳細:JSオブジェクトは連想配列であり、それが理由です。参考資料:quirksmode.org/js/associative.html stackoverflow.com/questions/14031368/...
Sudhanshuミシュラ

@dotnetguyいいえ、そうではありません。配列は、プレーンなJSオブジェクトプロトタイプから継承するオブジェクトであるため、プレーンオブジェクトと同様に、ゴーゴープロパティを追加できます。「連想」動作は、配列のようなものよりもオブジェクトのようなものです。単純なインデックスでは「連想」バージョンを反復できないため、配列のような動作は表示されません。ランダムプロパティアクセスに関する限り、「連想」配列を{}または[]として定義し、どちらの場合も同じように扱うことができます。
ヴァンク

3
@VanquishedWombatあなたの反対が何に関係するかわからないのですか?JSオブジェクトが配列であるとは言わなかったのですか?
Sudhanshu Mishra 2017

1
この回答は投票数が
多すぎる

104

これは私の解決策です:

function resolve(path, obj) {
    return path.split('.').reduce(function(prev, curr) {
        return prev ? prev[curr] : null
    }, obj || self)
}

使用例:

resolve("document.body.style.width")
// or
resolve("style.width", document.body)
// or even use array indexes
// (someObject has been defined in the question)
resolve("part.0.size", someObject) 
// returns null when intermediate properties are not defined:
resolve('properties.that.do.not.exist', {hello:'world'})

優秀な答えは、以下を参照してください。stackoverflow.com/questions/37510640/...
ジュリアン・ナイト

2
ブラケット表記とプロパティ名にスペースを使用できるようにするとともに、入力を検証できる拡張バージョンを作成するように私を促しました:it.knightnet.org.uk/kb/node-js/get-properties
Julian Knight

このソリューションが大好きです。しかし、私は元のオブジェクトの値を変更しようとしています、あなたの関数はオブジェクトのサブコピーを返すようです。返されたオブジェクトを変更すると元のオブジェクトが変更されるように変更することはできますか?
Eagle1

40

JavaScriptでは、次のようにアクセスできます。

  • ドット表記- foo.bar
  • 角括弧- foo[someVar]またはfoo["string"]

しかし、2番目のケースのみが動的にプロパティにアクセスできます。

var foo = { pName1 : 1, pName2 : [1, {foo : bar }, 3] , ...}

var name = "pName"
var num  = 1;

foo[name + num]; // 1

// -- 

var a = 2;
var b = 1;
var c = "foo";

foo[name + a][b][c]; // bar

4
以前の開発者が角括弧を使用しておらず、ドット表記で静的にオブジェクトプロパティにアクセスしていたため、ifステートメントの2,000行を見つめています。これは、7人の異なる承認者がいる承認プロセスアプリ用で、手順はすべて同じです。/ rip
Chad

26

以下は、2つの文字列を連結することによって動的に生成されたプロパティ名を使用してオブジェクトのプロパティにアクセスする方法のES6の例です。

var suffix = " name";

var person = {
    ["first" + suffix]: "Nicholas",
    ["last" + suffix]: "Zakas"
};

console.log(person["first name"]);      // "Nicholas"
console.log(person["last name"]);       // "Zakas"

これは計算されたプロパティ名と呼ばれます


16

これは、いくつかの方法で実現できます。

let foo = {
    bar: 'Hello World'
};

foo.bar;
foo['bar'];

ブラケット表記は、変数に基づいてプロパティにアクセスできるため、特に強力です。

let foo = {
    bar: 'Hello World'
};

let prop = 'bar';

foo[prop];

これは、オブジェクトのすべてのプロパティをループするように拡張できます。for ... of ...などの新しいJavaScriptコンストラクトのため、これは冗長に見えるかもしれませんが、ユースケースの説明に役立ちます。

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

for (let prop in foo.getOwnPropertyNames()) {
    console.log(foo[prop]);
}

ドット表記とブラケット表記のどちらも、ネストされたオブジェクトに対して期待どおりに機能します。

let foo = {
    bar: {
        baz: 'Hello World'
    }
};

foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;

オブジェクトの破壊

次のように、オブジェクトのプロパティにアクセスするための手段としてオブジェクトの構造化解除を検討することもできます。

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

let prop = 'last';
let { bar, baz, [prop]: customName } = foo;

// bar = 'Hello World'
// baz = 'How are you doing?'
// customName = 'Quite alright'

11

あなたはLodash getを使用してこのようにそれを行うことができます

_.get(object, 'a[0].b.c');

ディープネストされたオブジェクトルックアップなど、これが唯一のオプションである多くの状況があります。
ジョナサンケンプ

8

更新しました

以下のコメントを考慮に入れ、同意しました。評価は避けてください。

オブジェクトのルートプロパティへのアクセスはで簡単に実現できますobj[variable]が、入れ子にすると複雑になります。すでに書いたコードを書かないでくださいlodash.get

// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);

// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);

Lodash getはさまざまな方法で使用できます。ここにドキュメントlodash.getへのリンクがあります


4
eval可能な限り使用しないことをお勧めします。stackoverflow.com/questions/86513/...
ルーク

8
evalプロパティへのアクセスと同じくらい簡単なものに使用することは、やり過ぎであり、どのような状況でもほとんどお勧めできません。「トラブル」とは?obj['nested']['test']非常にうまく機能し、文字列にコードを埋め込む必要はありません。
Kyll

3
evalは3倍以上遅く、初心者には悪い習慣を教える可能性があるため、これをお勧めしません。私は使用していますobj['nested']['value']-子供を思い出してください、evalは悪です!
jaggedsoft 2015年

1
@ルーク彼はロダッシュ_.getをテーブルに連れてきたい唯一の望みです。この答えは、今では反対投票ではなく賛成投票に値すると思います。それはやり過ぎかもしれませんが、それが存在することを知るのは良いことです。
Emile Bergeron、2016

1
このためのlodashを導入していただきありがとうございます。私はここでgoogleによってオブジェクトの深い値を設定するメソッドを探して、それらの_.setメソッドを使用しました(これは上記と同じですが、値を設定するための追加の引数が必要です)。
TPHughes

5

プロパティに動的にアクセスする必要があるときはいつでも、 "。"ではなくプロパティにアクセスするために角括弧を使用する必要があります。演算子の
構文:object [propery}

const something = { bar: "Foobar!" };
const foo = 'bar';
// something.foo; -- not correct way at it is expecting foo as proprty in  something={ foo: "value"};
// correct way is  something[foo]
alert( something[foo])


4

オブジェクトプロパティの "アドレス"をデータとして別の関数に渡し、オブジェクトに(AJAXを使用して)データを入力し、アドレス配列からルックアップを行い、他の関数に表示したいと思った場合に遭遇しました。文字列の曲芸を行わずにドット表記を使用することはできなかったので、代わりに配列を渡すとよいと思いました。とにかく何か違うことをしてしまいましたが、この投稿に関連しているようです。

以下は、私がデータを取得したい言語ファイルオブジェクトのサンプルです。

const locs = {
  "audioPlayer": {
    "controls": {
      "start": "start",
      "stop": "stop"
    },
    "heading": "Use controls to start and stop audio."
  }
}

["audioPlayer"、 "controls"、 "stop"]などの配列を渡して、言語テキストにアクセスできるようにしたいと考えました。この場合は「stop」です。

「最も特定されていない」(最初の)アドレスパラメータを検索し、返されたオブジェクトをそれ自体に再割り当てするこの小さな関数を作成しました。次に、次に固有のアドレスパラメータが存在する場合は、それを検索する準備が整います。

function getText(selectionArray, obj) {
  selectionArray.forEach(key => {
    obj = obj[key];
  });
  return obj;
}

使用法:

/* returns 'stop' */
console.log(getText(["audioPlayer", "controls", "stop"], locs)); 

/* returns 'use controls to start and stop audio.' */
console.log(getText(["audioPlayer", "heading"], locs)); 

2

この関数にパラメーターを渡す必要がある場合にも興味深いです。

コード jsfiddle

var obj = {method:function(p1,p2,p3){console.log("method:",arguments)}}

var str = "method('p1', 'p2', 'p3');"

var match = str.match(/^\s*(\S+)\((.*)\);\s*$/);

var func = match[1]
var parameters = match[2].split(',');
for(var i = 0; i < parameters.length; ++i) {
  // clean up param begninning
    parameters[i] = parameters[i].replace(/^\s*['"]?/,'');
  // clean up param end
  parameters[i] = parameters[i].replace(/['"]?\s*$/,'');
}

obj[func](parameters); // sends parameters as array
obj[func].apply(this, parameters); // sends parameters as individual values

1

ES5 //深くネストされた変数をチェックする

この単純なコードは、途中で各変数をチェックする必要なく、深くネストされた変数/値の存在をチェックできます...

var getValue = function( s, context ){
    return Function.call( context || null, 'return ' + s )();
}

例 -深くネストされたオブジェクトの配列:

a = [ 
    {
      b : [
          {
             a : 1,
             b : [
                 {
                    c : 1,
                    d : 2   // we want to check for this
                 }
             ]
           }
      ]
    } 
]

の代わりに :

if(a && a[0] && a[0].b && a[0].b[0] && a[0].b[0].b && a[0].b[0].b[0] && a[0].b[0].b[0].d && a[0].b[0].b[0].d == 2 )  // true

私たちは今できます:

if( getValue('a[0].b[0].b[0].d') == 2 ) // true

乾杯!


1
解決策がevalを使用することである場合、100万の他の問題を作成しただけです。
Rodrigo Leite

@RodrigoLeiteわかりました。少なくとも1つ指定しても問題ありません...


1
@RodrigoLeite私はそれを読み、Function代わりに使用するソリューションを更新しました

0

私はしばらく前にこのトピックについて少し重複した質問をしました、そして過度の研究の後に、ここにあるはずの多くの情報が欠落しているのを見たとき、私はこの古い投稿に何か追加する価値があると思います。

  • まず、プロパティの値を取得して動的変数に格納するにはいくつかの方法があることを説明します。IMHOが最初に最も人気があり、最も簡単な方法は次のとおりです。
let properyValue = element.style['enter-a-property'];

ただし、スタイルシートを介して割り当てられたプロパティ値では機能しないため、このルートを使用することはほとんどありません。例を示すために、少しの疑似コードを使って説明します。

 let elem = document.getElementById('someDiv');
 let cssProp = elem.style['width'];

上記のコード例を使用します。'elem'変数に格納されたdiv要素のwidthプロパティがCSSスタイルシートでスタイル設定されていて、そのHTMLタグ内でスタイル設定されていない場合は、内部に保存されているundefinedの戻り値が返されることは間違いありません。 cssProp変数の。未定義の値が発生するのは、正しい値を取得するために、CSSスタイルシート内に記述されたコードを順番に計算して値を取得する必要があるためです。スタイルシート内にあるプロパティの値を計算するメソッドを使用する必要があります。

  • 以降getComputedStyle()メソッド!
function getCssProp(){
  let ele = document.getElementById("test");
  let cssProp = window.getComputedStyle(ele,null).getPropertyValue("width");
}

W3Schools getComputedValue Docこれは良い例であり、試してみることができますが、このリンクMozilla CSS getComputedValue DocはgetComputedValue関数について詳細に説明しており、この主題について完全に明確ではない開発者は読む必要があります。

  • 補足として、getComputedValueメソッドは取得のみを行い、設定は行いません。これは明らかに大きな欠点ですが、標準のJavaScriptではありませんが、CSSスタイルシートから取得して値を設定するメソッドがあります。JQueryメソッド...
$(selector).css(property,value)

...取得し、設定します。それが私が使用するものであり、唯一の欠点はあなたがJQueryを知るようになったことですが、これは正直言って、すべてのJavascript開発者がJQueryを学ぶべき非常に多くの正当な理由の1つです。標準のJavascriptでは使用できません。これが誰かを助けることを願っています!!!




-4
const something = { bar: "Foobar!" };
const foo = 'bar';

something[\`${foo}\`];

7
一体どうしてそんなことをするの?あなたfooはすでに文字列なので、`${foo}`とまったく同じfooです。(また、あなたのコードには、そこに属していない余分なバックスラッシュがいくつかあるようです。しかし、その構文エラーを修正しても、それはまだ無意味です。)
Ilmari Karonen '19
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.