Динамически получить доступ к объекту с помощью переменной

Я пытаюсь получить доступ к свойству объекта с использованием динамического имени. Возможно ли это?

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

Ответ 1

Существует два способа доступа к свойствам объекта:

  • Точечная нотация: something.bar
  • Кнопочная нотация: something['bar']

Значение между скобками может быть любым выражением. Поэтому, если имя свойства хранится в переменной, вы должны использовать нотацию в виде скобок:

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

Ответ 2

Это мое решение:

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

Ответ 3

В javascript мы можем получить доступ с помощью

  • точка нотации - foo.bar
  • квадратные скобки - foo[someVar] или foo["string"]

Но только второй случай позволяет динамически обращаться к свойствам:

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

Ниже приведен пример ES6 того, как вы можете получить доступ к свойству объекта, используя имя свойства, которое было динамически сгенерировано путем объединения двух строк.

var suffix = " name";

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

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

Это называется вычисленными именами свойств

Ответ 5

Вы можете достичь этого несколькими способами.

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

foo.bar;
foo['bar'];

Обозначение скобок особенно мощно, поскольку оно позволяет вам получить доступ к свойству, основанному на переменной:

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

let prop = 'bar';

foo[prop];

Это может быть расширено для циклизации по каждому свойству объекта. Это может казаться излишним из-за новых конструкций 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'

Ответ 6

Вы можете сделать это так, используя Lodash get

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

Ответ 7

ОБНОВЛЕНО

Я принял во внимание комментарии ниже и согласился. Эвала следует избегать.

Доступ к корневым свойствам объекта легко достигается с помощью 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

Ответ 8

Всякий раз, когда вам нужно динамически обращаться к свойству, вы должны использовать квадратную скобку для доступа к свойству, а не ".". оператор
Синтаксис: 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])

Ответ 9

Интересно, когда вам нужно передать параметры этой функции.

Код 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

Ответ 10

Например:

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

Вместо:

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

Вот код

/**
 * @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);
}

Ответ 11

Есть несколько возможностей:

const test = {
    prop1: {
      prop2: {
        prop3: "I'm very nested"
      }
    }

const test1 = test.prop1.prop2.prop3
const test2 = test['prop1']['prop2']['prop3']
const test3 = test['prop1.prop2.prop3'] //will return undefined
const test4 = _.get(test, 'prop1.prop2.prop3') //use lodash

Если вы хотите получить вложенное значение динамически (например, по переменной), лучшим вариантом будет использование lodash.

Ответ 12

Вы должны использовать JSON.parse, посмотрите https://www.w3schools.com/js/js_json_parse.asp

const obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}')
console.log(obj.name)
console.log(obj.age)

Ответ 13

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

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

Ответ 14

Вот способ получения свойства или вложенного объекта из объекта с использованием нотации пути. Это адаптация аналогичного вопроса, заданного "Пруспрусом" в 2014 году.

У меня есть файл конфигурации с вложенными массивами и вы хотите получить доступ к данным с веб-страницы, отправив путь в форме:

"unit_cfg [2].chn_cfg [7].chn_type"

Эта функция вернет одно свойство или объект. Да, это можно упростить...

function fetchFromObject(obj: Object, path: string): boolean | Object {
var dot_idx: number;
var lbkt_idx: number;
var rbkt_idx: number;
var prop: string;
var prop_idx: number;
var new_obj: Object;
var new_path: string;

// Return if no object.
if (typeof obj === 'undefined') {
    return false;
}

// Get index of first left bracket in path.
lbkt_idx = path.indexOf('[');
// If left bracket.
if (lbkt_idx > -1) {
    // Get right bracket index.
    rbkt_idx = path.indexOf(']');
}
// Get index of first dot in path.
dot_idx = path.indexOf('.');

/*
 * Most complicated situation is if there are both brackets
 * and dots in the path. This means we have a mixture of both
 * indexed and non-indexed properties:
 *
 *      x[].y --or-- x.y[]
 *
 * In this case, we must see if the indexed property is before
 * or after the non-indexed property.
 *
 * In either case, we must recurse.
 */
if ((lbkt_idx > -1) && (dot_idx > -1)) {
    // If bracket is before dot: x[].y
    if (lbkt_idx < dot_idx) {
        // Get property string.
        prop = path.substr(0, lbkt_idx);
        // Get index.
        prop_idx = Number(path.substring(lbkt_idx + 1, rbkt_idx));
        // Get path to right of dot.
        new_path = path.substr(dot_idx + 1);
        // Get new object.
        new_obj = obj[prop][prop_idx];
        // Recurse.
        return fetchFromObject(new_obj, new_path);
    }
    // Else dot before bracket: x.y[]
    else {
        // Get property string.
        prop = path.substr(0, dot_idx);
        // Get path to right of dot.
        new_path = path.substr(dot_idx + 1);
        // Get new object.
        new_obj = obj[prop];
        // Recurse.
        return fetchFromObject(new_obj, new_path);
    }
}
/*
 * Else recurse if dotted property; x.y
 */
else if (dot_idx > -1) {
    // Get property string.
    prop = path.substr(0, dot_idx);
    // Get path to right of dot.
    new_path = path.substr(dot_idx + 1);
    // Get new object.
    new_obj = obj[prop];
    // Recurse.
    return fetchFromObject(new_obj, new_path);
}
/*
 * Else done if single indexed property: x[]
 */
else if (lbkt_idx > -1) {
    // Get property string.
    prop = path.substr(0, lbkt_idx);
    // Get index.
    prop_idx = Number(path.substring(lbkt_idx + 1, rbkt_idx));
    // Return with object.
    return obj[prop][prop_idx];
}
/*
 * Else single non-indexed property.
 */
return obj[path];

}