web-dev-qa-db-de.com

Greifen Sie dynamisch mit einer Variablen auf die Objekteigenschaft zu

Ich versuche, unter Verwendung eines dynamischen Namens auf eine Eigenschaft eines Objekts zuzugreifen. Ist das möglich?

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

Es gibt zwei Möglichkeiten, auf Eigenschaften zuzugreifen eines Objekts:

  • Punktnotation: something.bar
  • Klammernotation: something['bar']

Der Wert zwischen den Klammern kann ein beliebiger Ausdruck sein. Wenn der Eigenschaftsname in einer Variablen gespeichert ist, müssen Sie daher die Klammernotation verwenden:

var foo = 'bar';
something[foo];
// both x = something[foo] and something[foo] = x work as expected
824
Jan Hančič

Das ist meine Lösung:

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

Anwendungsbeispiele:

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'})
73
abahet

In Javascript können wir zugreifen mit:

  • punktnotation - foo.bar
  • eckige Klammern - foo[someVar] oder foo["string"]

Aber nur der zweite Fall ermöglicht den dynamischen Zugriff auf Eigenschaften:

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
33
Sonique

Im Folgenden finden Sie ein ES6-Beispiel für den Zugriff auf die Eigenschaft eines Objekts unter Verwendung eines Eigenschaftsnamens, der dynamisch durch Verketten zweier Zeichenfolgen generiert wurde.

var suffix = " name";

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

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

Dies wird berechnete Eigenschaftsnamen genannt

20
zloctb

Sie können dies auf ganz verschiedene Arten erreichen.

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

foo.bar;
foo['bar'];

Die Klammer-Notation ist besonders mächtig, da Sie auf eine Eigenschaft zugreifen können, die auf einer Variablen basiert:

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

let prop = 'bar';

foo[prop];

Dies kann so erweitert werden, dass alle Eigenschaften eines Objekts durchlaufen werden. Dies kann aufgrund neuerer JavaScript-Konstrukte wie für ... of ... als redundant erscheinen, dient jedoch zur Veranschaulichung eines Anwendungsfalls:

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

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

Sowohl die Punkt- als auch die Klammernotation funktionieren für verschachtelte Objekte wie erwartet:

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

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

Objektdestrukturierung

Wir könnten die Objektdestrukturierung auch als Mittel zum Zugriff auf eine Eigenschaft in einem Objekt betrachten, aber wie folgt:

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'
15
Gorka Hernandez

Du kannst es so mit Lodash get machen

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

AKTUALISIERT

Ich habe die folgenden Kommentare berücksichtigt und bin damit einverstanden. Eval ist zu vermeiden.

Der Zugriff auf Root-Eigenschaften in object ist mit obj[variable] leicht möglich, aber das Verschachteln erschwert die Sache. Um keinen bereits geschriebenen Code zu schreiben, empfehle ich lodash.get.

Beispiel

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

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

Lodash get kann auf verschiedene Arten verwendet werden, hier ist der Link zur Dokumentation lodash.get

8
Mr Br

Immer wenn Sie dynamisch auf eine Eigenschaft zugreifen müssen, müssen Sie eine eckige Klammer verwenden, um auf eine Eigenschaft zuzugreifen, nicht "." Operator
Syntax: 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])
5
Rupesh Agrawal

Interessant wird es, wenn Sie auch dieser Funktion Parameter übergeben müssen.

Code 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
2
Jacksonkr

Beispielsweise :

a = [ {b:[{a:1,b:[{c:1,d:2}]}]} ]

Anstatt :

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

Wir können jetzt:

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

Hier ist der Code

/**
 * @method getValue
 * @description simplifies checking for existance and getting a deeply nested value within a ceratin context
 * @argument {string} s       string representation of the full path to the requested property 
 * @argument {object} context optional - the context to check defaults to window
 * @returns the value if valid and set, returns undefined if invalid / not available etc.
 */
var getValue = function( s, context ){
    var fn = function(){
        try{
            return eval(s);
        }catch(e){
            return undefined;
        }
    }
    return fn.call(context||window,s);
}
0
levi