В javascript, как я могу динамически получить вложенное свойство объекта - PullRequest
27 голосов
/ 02 августа 2011
var arr = { foo : 1, bar: { baz : 2 }, bee : 3 }

function getter(variable) {
  return arr[variable];
}

Если я хочу «foo» против «пчелы», я могу просто сделать arr[variable] - это легко, и функция делает это.

Но что, если я хочу получить arr.bar.baz АКА arr[bar][baz]?

Что я могу передать функции получения, которая позволит мне это делать (и, конечно, также позволяет мне получить не вложенные свойства, используя ту же функцию).

Я пытался getter('bar.baz') и getter('[bar][baz]'), но они не работали.

Полагаю, я могу разобрать точки или скобки (например, здесь: В javascript проверить свойство, глубоко вложенное в граф объектов? ). Есть ли более чистый способ? (Кроме Eval конечно.)

Тем более, что мне нужно много раз правильно настроить глубоко заданные циклы для набора элементов массива.

Ответы [ 8 ]

39 голосов
/ 02 августа 2011

Вы можете использовать функцию глубокого доступа на основе строки для пути. Обратите внимание, что в именах свойств не должно быть периодов.

function getPropByString(obj, propString) {
    if (!propString)
        return obj;

    var prop, props = propString.split('.');

    for (var i = 0, iLen = props.length - 1; i < iLen; i++) {
        prop = props[i];

        var candidate = obj[prop];
        if (candidate !== undefined) {
            obj = candidate;
        } else {
            break;
        }
    }
    return obj[props[i]];
}

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

alert(getPropByString(obj, 'foo.bar.baz')); // x
alert(getPropByString(obj, 'foo.bar.baz.buk')); // undefined

Если строка доступа пуста, возвращает объект. В противном случае, продолжает идти по пути доступа до второго последнего доступа. Если это объект, возвращает последнее значение object[accessor]. В противном случае возвращает неопределенное значение.

18 голосов
/ 24 ноября 2015

Лучше всего использовать методы библиотеки lodash: - https://lodash.com/docs#get

_.get(arr, 'bar.baz'); //returns 2;
_.get(arr, 'bar.baz[5].bazzz'); //returns undefined wont throw error;
_.get(arr, 'bar.baz[5].bazzz', 'defaultvalue'); // Returns defaultValue because result is undefined 
9 голосов
/ 02 августа 2011

Как насчет изменения сигнатуры функции получения как getter('bar', 'baz') вместо

function getter() {
  var v = arr;
  for(var i=0; i< arguments.length; i++) {
    if(!v) return null;
    v = v[arguments[i]];
  }
  return v;
}

пс. не проверял, но вы поняли;)

2 голосов
/ 10 мая 2019

A один вкладыш для вас:

const mock = {
  target: {
    "prop1": {
      "prop2": {
        "prop3": "sad"
      }
    }
  },
  path: "prop1.prop2.prop3",
  newValue: "happy"
};

mock.path.split(".").reduce(
  (acc, curr, i, src) =>
    (curr === src[src.length - 1]) ? acc[src[src.length - 1]] = mock.newValue : acc[curr], mock.target);


console.log(mock.target); //? { prop1: { prop2: { prop3: 'happy' } } }
1 голос
/ 07 июля 2019

Рекурсивный способ:

   function getValue(obj, path) {
        if (!path) return obj;
        const properties = path.split('.');
        return getValue(obj[properties.shift()], properties.join('.'))
    }

    const myObj = {
        foo: {
            bar: {
                value: 'good'
            }
        }
    }

    console.log(getValue(myObj, 'foo.bar.value')); // good
1 голос
/ 06 мая 2016

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

Object.prototype.getNestedValue = function(...a) {
  return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};

var myObj = { foo : 1, bar: { baz : 2 }, bee : 3 },
   bazval = myObj.getNestedValue("bar","baz");

document.write(bazval);

Теперь давайте проверим структуру комбинированных данных объекта с более глубоким вложенным массивом

Object.prototype.getNestedValue = function(...a) {
  return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};

var myArr = [{fox: [{turn:[857, 432]}]}, {sax: [{pana:[777, 987]}]}, {ton: [{joni:[123, 567]}]}, {piu: [{burn:[666, 37]}]}, {sia: [{foxy:[404, 696]}]}];
  
document.write(myArr.getNestedValue(3,"piu",0,"burn",1));

Я считаю, что возможность динамически передавать параметры поиска в существующие методы массива значительно упростит такие действия, как поиск, фильтрация или замена глубоко вложенных структур.

1 голос
/ 12 апреля 2013

Theres функция, определенная в этом блоге для безопасного чтения вложенных свойств из объекта JS

. Она позволяет вам добывать объект для свойств ... то есть.

safeRead(arr, 'foo', 'bar', 'baz');

и если какая-либо часть цепочки объектов равна нулю или не определена, она возвращает пустую строку ....

1 голос
/ 02 августа 2011

Вы можете получить доступ к аргументам функций, где вы можете передать любое количество строк. Я также рекомендую использовать arr в качестве параметра для лучшей инкапсуляции:

function getter() {
    var current = arguments[0];
    for(var i = 1; i < arguments.length; i++) {
        if(current[arguments[i]]) {
            current = current[arguments[i]];
        } else {
            return null;
        }
    }
    return current;
}

var arr = { foo : 1, bar: { baz : 2 }, bee : 3 };
var baz = getter(arr, 'bar', 'baz');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...