В javascript я могу динамически получить вложенное свойство объекта
var arr = { foo : 1, bar: { baz : 2 }, bee : 3 }
function getter(variable) {
return arr[variable];
}
Если я хочу 'foo' vs 'bee', я могу просто сделать arr[variable]
- это просто, и функция делает это.
Но что, если я хочу получить arr.bar.baz
AKA arr[bar][baz]
?
Что я могу передать функции getter, которая позволит мне это сделать (и, конечно, также позвольте мне получить не-вложенные свойства, используя одну и ту же функцию).
Я пробовал getter('bar.baz')
и getter('[bar][baz]')
, но они не работали.
Я полагаю, что могу анализировать точки или скобки (например, здесь: В javascript, тест для свойства, глубоко вложенного в графа объектов?). Есть ли более чистый способ? (Кроме того, eval, конечно.)
Особенно потому, что мне нужно многократно установить множество много раз в цикле для группировки элементов массива.
Ответы
Ответ 1
Как изменить подпись функции getter как 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
Вы можете использовать функцию глубокого доступа, основанную на строке для пути. Обратите внимание, что вы не можете иметь никаких периодов в именах свойств.
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
Если строка доступа пуста, возвращает объект. В противном случае, продолжайте движение по пути доступа до второго последнего доступа. Если это ojbect, возвращает последнее значение object[accessor]
. В противном случае возвращает undefined.
Ответ 3
Использование ES6: -
var arr = { foo : 1, bar: { baz : 2 }, bee : 3 };
var {foo, bar, bar: {baz}, bee} = arr;
То же, что и
// var foo = 1;
// var bar = {baz: 2};
// var baz = 2;
// var bee = 3;
Использование 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
Ответ 4
Один лайнер для вас:
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' } } }
Ответ 5
Вы можете получить доступ к аргументам функций, в которых вы можете передать любое количество строк.
Я также рекомендую использовать параметр 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');
Ответ 6
В этой статье функция позволяет безопасно читать вложенные свойства объекта JS
Это позволяет вам разминировать объект для свойств... т.е.
safeRead(arr, 'foo', 'bar', 'baz');
и если какая-либо часть цепочки объектов равна null или undefined, она возвращает пустую строку....
Ответ 7
Недавно я разработал свой собственный метод 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);
Ответ 8
Рекурсивный способ:
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