/ Процесса (вложенные) объекты, массивы или JSON
у меня есть вложенная структура данных, содержащая объекты и массивы. Как я могу извлечь информацию, т. е. получить доступ к определенным или нескольким значениям (или ключам)?
например:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
как я мог получить доступ к name
второй элемент items
?
20 ответов
квалификации
JavaScript имеет только один тип данных, который может содержать несколько значений: объект. Ан массив является особой формой объекта.
(простые) объекты имеют форму
{key: value, key: value, ...}
массивы имеют вид
[value, value, ...]
как массивы, так и объекты выставляют key -> value
структура. Ключи в массиве должны быть числовыми, тогда как любая строка может использоваться в качестве ключа в объектах. Пары ключ-значение также называются the "свойства".
свойства могут быть доступны либо с помощью точку
const value = obj.someProperty;
или скобочная нотация, если имя свойства не будет допустимым JavaScript имя идентификатора [spec], или имя является значением переменной:
// the space is not a valid character in identifier names
const value = obj["some Property"];
// property name as variable
const name = "some Property";
const value = obj[name];
по этой причине доступ к элементам массива можно получить только с помощью кронштейна обозначение:
const value = arr[5]; // arr.5 would be a syntax error
// property name / index as variable
const x = 5;
const value = arr[x];
подождать... что о JSON?
JSON-это текстовое представление данных, как XML, YAML, CSV и другие. Для работы с такими данными его сначала нужно преобразовать в типы данных JavaScript, т. е. массивы и объекты (и как с ними работать, было только что объяснено). Как разбирать JSON объясняется в вопросе анализировать JSON в JavaScript? .
дальнейшее чтение материала
как получить доступ к массивам и объекты являются фундаментальными знаниями JavaScript, и поэтому рекомендуется прочитать MDN JavaScript Guide, особенно разделы
доступ к вложенным структурам данных
вложенная структура данных-это массив или объект, который относится к другим массивам или объектам, т. е. его значения являются массивами или объектами. К таким структурам можно получить доступ, последовательно применяя точечную или скобочную нотацию.
вот пример:
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
предположим, мы хотим получить доступ к name
второй пункт.
вот как мы можем сделать это шаг за шагом:
как видим data
является объектом, поэтому мы можем получить доступ к его свойствам с помощью точечной нотации. The items
агроусадьбы следующим образом:
data.items
значение является массивом, для доступа к его второму элементу мы должны использовать скобочную нотацию:
data.items[1]
это значение является объектом, и мы снова используем точечную нотацию для доступа к name
собственность. Таким образом, мы в конечном итоге получаем:
const item_name = data.items[1].name;
кроме того, мы могли бы использовать скобочную нотацию для любого из свойств, особенно если имя содержит символы, которые сделали бы его недопустимым для точечной нотации использование:
const item_name = data['items'][1]['name'];
я пытаюсь получить доступ к свойству, но я получаю только undefined
обратно?
большую часть времени, когда вы получаете undefined
, объект / массив просто не имеет свойства с этим именем.
const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined
использовать console.log
или console.dir
и проверьте структуру объекта / массива. Свойство, к которому вы пытаетесь получить доступ, может быть фактически определено во вложенном объекте / матрица.
console.log(foo.bar.baz); // 42
что делать, если имена свойств являются динамическими, и я не знаю их заранее?
если имена свойств неизвестны или мы хотим получить доступ ко всем свойствам объекта или элементы массива, мы можем использовать for...in
[MDN] цикл для объектов и for
[MDN] цикл для массивов для итерации по всем свойствам / элементы.
объекты
для перебора всех свойств data
, мы можем перебирать объект вот так:
for (const prop in data) {
// `prop` contains the name of each property, i.e. `'code'` or `'items'`
// consequently, `data[prop]` refers to the value of each property, i.e.
// either `42` or the array
}
в зависимости от того, откуда берется объект (и что вы хотите сделать), вам может потребоваться проверить на каждой итерации, действительно ли свойство является свойством объекта или унаследованным свойством. Вы можете сделать это с помощью Object#hasOwnProperty
[MDN].
в качестве альтернативы for...in
С hasOwnProperty
, вы можете использовать Object.keys
[MDN] для получения массив имен свойств:
Object.keys(data).forEach(function(prop) {
// `prop` is the property name
// `data[prop]` is the property value
});
массивы
для итерации по всем элементам data.items
массив, мы используем for
петли:
for(let i = 0, l = data.items.length; i < l; i++) {
// `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
// we can access the next element in the array with `data.items[i]`, example:
//
// var obj = data.items[i];
//
// Since each element is an object (in our example),
// we can now access the objects properties with `obj.id` and `obj.name`.
// We could also use `data.items[i].id`.
}
можно использовать for...in
перебрать массивы, но есть причины, по которым этого следует избегать:почему "for(элемент var в списке)" с массивами считается плохой практикой в JavaScript?.
С увеличением поддержки браузера ECMAScript 5 метод массива forEach
[MDN] становится интересной альтернативой:
data.items.forEach(function(value, index, array) {
// The callback is executed for each element in the array.
// `value` is the element itself (equivalent to `array[index]`)
// `index` will be the index of the element in the array
// `array` is a reference to the array itself (i.e. `data.items` in this case)
});
в средах, поддерживающих ES2015 (ES6), вы также можете использовать for...of
[MDN] цикл, который работает не только для массивов, но и для любого типа Iterable:
for (const item of data.items) {
// `item` is the array element, **not** the index
}
в каждой итерации, for...of
непосредственно дает нам следующий элемент iterable, нет "индекса" для доступа или использования.
что делать, если "глубина" структуры данных мне неизвестен?
в дополнение к неизвестным ключам, "глубина" структуры данных (т. е. сколько вложенных objects), он также может быть неизвестен. Как получить доступ к глубоко вложенным свойствам обычно зависит от точной структуры данных.
но если структура данных содержит повторяющиеся шаблоны, например представление двоичного дерева, решение обычно включает в себя рекурсивно [Википедия] доступ к каждому уровню структуры данных.
вот пример получения первого листового узла двоичного файла дерево:
function getLeaf(node) {
if (node.leftChild) {
return getLeaf(node.leftChild); // <- recursive call
}
else if (node.rightChild) {
return getLeaf(node.rightChild); // <- recursive call
}
else { // node must be a leaf node
return node;
}
}
const first_leaf = getLeaf(root);
const root = {
leftChild: {
leftChild: {
leftChild: null,
rightChild: null,
data: 42
},
rightChild: {
leftChild: null,
rightChild: null,
data: 5
}
},
rightChild: {
leftChild: {
leftChild: null,
rightChild: null,
data: 6
},
rightChild: {
leftChild: null,
rightChild: null,
data: 7
}
}
};
function getLeaf(node) {
if (node.leftChild) {
return getLeaf(node.leftChild);
} else if (node.rightChild) {
return getLeaf(node.rightChild);
} else { // node must be a leaf node
return node;
}
}
console.log(getLeaf(root).data);
более общий способ доступа к вложенной структуре данных с неизвестными ключами и глубиной-проверить тип значения и действовать соответственно.
вот пример, который добавляет все примитивные значения внутри вложенной структуры данных в массив (если он не содержит каких-либо функций). Если мы сталкиваемся с объектом (или массивом), мы просто вызываем toArray
снова об этом значении (рекурсивное призывать.)
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value)); // <- recursive call
}
else {
result.push(value);
}
}
return result;
}
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value));
} else {
result.push(value);
}
}
return result;
}
console.log(toArray(data));
хелперы
поскольку структура сложного объекта или массива не обязательно очевидна, мы можем проверять значение на каждом шаге, чтобы решить, как двигаться дальше. console.log
[MDN] и console.dir
[MDN] помогите нам сделать это. Например (вывод хрома консоль):
> console.log(data.items)
[ Object, Object ]
здесь мы видим, что data.items
- это массив с двумя элементами, которые являются как объекты. В консоли Chrome объекты могут быть расширены и немедленно проверены.
> console.log(data.items[1])
Object
id: 2
name: "bar"
__proto__: Object
это говорит нам о том, что data.items[1]
является объектом, и после его расширения мы видим, что он имеет три свойства,id
, name
и __proto__
. Последнее является внутренним свойством, используемым для цепочки прототипов объекта. Цепочка прототипов и наследование отсутствуют тем не менее, для этого ответа.
Вы можете получить доступ к нему таким образом
data.items[1].name
или
data["items"][1]["name"]
оба пути равны.
в случае если вы пытаетесь получить доступ к item
из примера структуры id
или name
, не зная его позиции в массиве, самый простой способ сделать это было бы использовать подчеркивания.js библиотека:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
_.find(data.items, function(item) {
return item.id === 2;
});
// Object {id: 2, name: "bar"}
из моего опыта, используя функции высшего порядка вместо for
или for..in
циклы приводят к коду, который легче рассуждать, и, следовательно, более ремонтопригоден.
только мои 2 цента.
иногда доступ к вложенному объекту с помощью строки может быть желательным. Простой подход-это первый уровень, например
var obj = { hello: "world" };
var key = "hello";
alert(obj[key]);//world
но это часто не так со сложным json. Поскольку json становится более сложным, подходы к поиску значений внутри json также становятся сложными. Рекурсивный подход для навигации по json лучше всего, и то, как эта рекурсия используется, будет зависеть от типа данных, которые ищут. Если существуют условные операторы участвуют,поиск json может быть хорошим инструментом для использования.
если свойство, к которому осуществляется доступ, уже известно, но путь сложный, например, в этом объекте
var obj = {
arr: [
{ id: 1, name: "larry" },
{ id: 2, name: "curly" },
{ id: 3, name: "moe" }
]
};
и вы знаете, что хотите получить первый результат массива в объекте, возможно, вы хотели бы использовать
var moe = obj["arr[0].name"];
однако это вызовет исключение, поскольку нет свойства объекта с этим именем. Решение сможете использовать это будет разогнуть дерево аспект объекта. Это можно сделать рекурсивно.
function flatten(obj){
var root = {};
(function tree(obj, index){
var suffix = toString.call(obj) == "[object Array]" ? "]" : "";
for(var key in obj){
if(!obj.hasOwnProperty(key))continue;
root[index+key+suffix] = obj[key];
if( toString.call(obj[key]) == "[object Array]" )tree(obj[key],index+key+suffix+"[");
if( toString.call(obj[key]) == "[object Object]" )tree(obj[key],index+key+suffix+".");
}
})(obj,"");
return root;
}
теперь сложный объект может быть сплющен
var obj = previous definition;
var flat = flatten(obj);
var moe = flat["arr[0].name"];//moe
здесь jsFiddle Demo
этот подход используется.
объекты и массивы имеют множество встроенных методов, которые могут помочь вам в обработке данных.
Примечание: во многих примерах я использую функции стрелочку. Они похожи на выражения функции, но они связывают this
значение лексически.
Object.keys()
, Object.values()
(ES 2017) и Object.entries()
(ES 2017)
Object.keys()
возвращает массив ключей объекта, Object.values()
возвращает массив значений объекта, и Object.entries()
возвращает массив ключей объекта и соответствующие значения в формате [key, value]
.
const obj = {
a: 1
,b: 2
,c: 3
}
console.log(Object.keys(obj)) // ['a', 'b', 'c']
console.log(Object.values(obj)) // [1, 2, 3]
console.log(Object.entries(obj)) // [['a', 1], ['b', 2], ['c', 3]]
Object.entries()
С циклом for-of и назначением деструктурирования
const obj = {
a: 1
,b: 2
,c: 3
}
for (const [key, value] of Object.entries(obj)) {
console.log(`key: ${key}, value: ${value}`)
}
очень удобно повторять результат Object.entries()
С for-of loop и реструктуризующее присваивание.
for-of loop позволяет выполнять итерацию элемент массива. Синтаксис for (const element of array)
(мы можем заменить const
С var
или let
, но лучше использовать const
если мы не намерены изменять element
).
назначение деструктурирования позволяет извлекать значения из массива или объекта и назначать их переменным. В этом случае const [key, value]
означает, что вместо назначения [key, value]
массива element
, мы назначаем первый элемент этого массива key
второй элемент value
. Это эквивалентно это:
for (const element of Object.entries(obj)) {
const key = element[0]
,value = element[1]
}
как вы можете видеть, разрушение делает это намного проще.
Array.prototype.every()
и Array.prototype.some()
на every()
возвращает true
если указанная функция обратного вызова возвращает true
на элемент массива. The some()
возвращает true
если указанная функция обратного вызова возвращает true
на некоторые (по крайней мере, один) элемент.
const arr = [1, 2, 3]
// true, because every element is greater than 0
console.log(arr.every(x => x > 0))
// false, because 3^2 is greater than 5
console.log(arr.every(x => Math.pow(x, 2) < 5))
// true, because 2 is even (the remainder from dividing by 2 is 0)
console.log(arr.some(x => x % 2 === 0))
// false, because none of the elements is equal to 5
console.log(arr.some(x => x === 5))
Array.prototype.find()
и Array.prototype.filter()
на find()
возвращает методов первый элемент, который удовлетворяет предоставленной функции обратного вызова. The filter()
метод возвращает массив все элементы, удовлетворяющие предоставленной функции обратного вызова.
const arr = [1, 2, 3]
// 2, because 2^2 !== 2
console.log(arr.find(x => x !== Math.pow(x, 2)))
// 1, because it's the first element
console.log(arr.find(x => true))
// undefined, because none of the elements equals 7
console.log(arr.find(x => x === 7))
// [2, 3], because these elements are greater than 1
console.log(arr.filter(x => x > 1))
// [1, 2, 3], because the function returns true for all elements
console.log(arr.filter(x => true))
// [], because none of the elements equals neither 6 nor 7
console.log(arr.filter(x => x === 6 || x === 7))
Array.prototype.map()
в map()
метод возвращает массив с результатами вызова предоставленной функции обратного вызова на элементах массива.
const arr = [1, 2, 3]
console.log(arr.map(x => x + 1)) // [2, 3, 4]
console.log(arr.map(x => String.fromCharCode(96 + x))) // ['a', 'b', 'c']
console.log(arr.map(x => x)) // [1, 2, 3] (no-op)
console.log(arr.map(x => Math.pow(x, 2))) // [1, 4, 9]
console.log(arr.map(String)) // ['1', '2', '3']
Array.prototype.reduce()
на reduce()
метод уменьшает массив до одного значения, вызывая предоставленную функцию обратного вызова с двумя элементами.
const arr = [1, 2, 3]
// Sum of array elements.
console.log(arr.reduce((a, b) => a + b)) // 6
// The largest number in the array.
console.log(arr.reduce((a, b) => a > b ? a : b)) // 3
на reduce()
метод принимает необязательный второй параметр, который является начальным значением. Это полезно когда массив, на который вы вызываете reduce()
can имеет ноль или один элемент. Например, если мы хотим создать функцию sum()
, который принимает массив в качестве аргумента и возвращает сумму всех элементов, мы могли бы написать так:
const sum = arr => arr.reduce((a, b) => a + b, 0)
console.log(sum([])) // 0
console.log(sum([4])) // 4
console.log(sum([2, 5])) // 7
этот вопрос довольно старый, так как современный обновления. С наступлением ES2015 есть альтернативы, чтобы получить необходимые данные. Теперь есть функция под названием объект деструктурируется для доступа к вложенным объектам.
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
const {
items: [, {
name: secondName
}]
} = data;
console.log(secondName);
в приведенном выше примере создается переменная с именем secondName
С name
ключ из массива под названием items
- одинокая ,
говорит пропустить первый объект в массиве.
в частности, вероятно, это перебор для этого примера, так как простой массив легче читать, но он полезен при разбиении объектов в целом.
Это очень краткое введение в ваш конкретный случай использования, деструктурирование может быть необычным синтаксисом, к которому нужно привыкнуть сначала. Я бы рекомендовал читать Mozilla деструктурирования документации назначения чтобы узнать больше.
используя помощью jsonpath будет одним из самых гибких решений, если вы готовы включить библиотеку: https://github.com/s3u/JSONPath (узел и браузер)
для вашего варианта использования путь json будет:
$..items[1].name
так:
var secondName = jsonPath.eval(data, "$..items[1].name");
Я предпочитаю JQuery. Это чище и легко читать.
$.each($.parseJSON(data), function (key, value) {
alert(value.<propertyname>);
});
для доступа к вложенному атрибуту необходимо указать его имя, а затем выполнить поиск по объекту.
если вы уже знаете точный путь, то вы можете жестко закодировать его в своем скрипте следующим образом:
data['items'][1]['name']
они также работают -
data.items[1].name
data['items'][1].name
data.items[1]['name']
когда вы не знаете точное имя перед рукой, или пользователь тот, кто предоставляет имя для вас. Затем требуется динамический поиск по структуре данных. Некоторые предположили здесь, что поиск может быть сделано с помощью for
цикл, но есть очень простой способ пересечь путь с помощью Array.reduce
.
const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }
const path = [ 'items', '1', 'name']
let result = path.reduce((a,v) => a[v], data)
путь-это способ сказать: сначала возьмите объект с ключом items
, который является массивом. Тогда возьмите 1
-й элемент (0 массивы индексов). Последний взять объект с ключом name
в этом элементе массива, который является строкой bar
.
если у вас очень длинный путь, вы можете даже использовать String.split
чтобы сделать все это проще -
'items.1.name'.split('.').reduce((a,v) => a[v], data)
это просто JavaScript, без использования каких-либо сторонних библиотек, таких как jQuery или lodash.
если вы ищете один или несколько объектов, отвечающих определенным критериям, у вас есть несколько вариантов использования запрос-js
//will return all elements with an id larger than 1
data.items.where(function(e){return e.id > 1;});
//will return the first element with an id larger than 1
data.items.first(function(e){return e.id > 1;});
//will return the first element with an id larger than 1
//or the second argument if non are found
data.items.first(function(e){return e.id > 1;},{id:-1,name:""});
там же single
и singleOrDefault
они работают так же, как first
и firstOrDefault
соответственно. Разница только в том, что они будут бросать, если больше совпадений не найдено.
для дальнейшего объяснения query-js вы можете начать с этого в должности
можно использовать lodash _get
функция:
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, 'a[0].b.c');
// => 3
путь подчеркивания js
который является библиотекой JavaScript, которая обеспечивает целый беспорядок полезного functional programming
помощники без расширения встроенных объектов.
устранение:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
var item = _.findWhere(data.items, {
id: 2
});
if (!_.isUndefined(item)) {
console.log('NAME =>', item.name);
}
//using find -
var item = _.find(data.items, function(item) {
return item.id === 2;
});
if (!_.isUndefined(item)) {
console.log('NAME =>', item.name);
}
Я не думаю, что questioner касается только одного вложенного объекта уровня, поэтому я представляю следующую демонстрацию, чтобы продемонстрировать, как получить доступ к узлу глубоко вложенного объекта json. Хорошо, давайте найдем узел с id '5'.
var data = {
code: 42,
items: [{
id: 1,
name: 'aaa',
items: [{
id: 3,
name: 'ccc'
}, {
id: 4,
name: 'ddd'
}]
}, {
id: 2,
name: 'bbb',
items: [{
id: 5,
name: 'eee'
}, {
id: 6,
name: 'fff'
}]
}]
};
var jsonloop = new JSONLoop(data, 'id', 'items');
jsonloop.findNodeById(data, 5, function(err, node) {
if (err) {
document.write(err);
} else {
document.write(JSON.stringify(node, null, 2));
}
});
<script src="https://rawgit.com/dabeng/JSON-Loop/master/JSONLoop.js"></script>
старый вопрос, но как никто не упоминал lodash (просто подчеркните).
если вы уже используете lodash в своем проекте, я думаю, что элегантный способ сделать это в сложном примере:
Opt 1
_.get(response, ['output', 'fund', 'data', '0', 'children', '0', 'group', 'myValue'], '')
то же, что:
Opt 2
response.output.fund.data[0].children[0].group.myValue
разница между первым и вторым вариантом заключается в том, что в Opt 1 если у вас отсутствует одно из свойств (не определено) в path вы не получаете ошибку, она возвращает вам третий параметр.
для фильтра массива lodash имеет _.find()
но я бы предпочел использовать обычный filter()
. Но я все еще думаю, что вышеуказанный метод _.get()
очень полезно при работе с очень сложными данными. Я столкнулся в прошлом действительно сложные APIs, и это было удобно!
Я надеюсь, что это может быть полезно для тех, кто ищет варианты манипулирования действительно сложными данными, которые подразумевает название.
доступ к динамически многоуровневому объекту.
var obj = {
name: "salut",
subobj: {
subsubobj: {
names: "I am sub sub obj"
}
}
};
var level = "subobj.subsubobj.names";
level = level.split(".");
var currentObjState = obj;
for (var i = 0; i < level.length; i++) {
currentObjState = currentObjState[level[i]];
}
console.log(currentObjState);
рабочая скрипка: https://jsfiddle.net/andreitodorut/3mws3kjL/
var ourStorage = {
"desk": {
"drawer": "stapler"
},
"cabinet": {
"top drawer": {
"folder1": "a file",
"folder2": "secrets"
},
"bottom drawer": "soda"
}
};
ourStorage.cabinet["top drawer"].folder2; // Outputs -> "secrets"
или
//parent.subParent.subsubParent["almost there"]["final property"]
В основном, используйте точку между каждым потомком, который разворачивается под ним, и когда у вас есть имена объектов, сделанные из двух строк, вы должны использовать нотацию ["obj Name"]. В противном случае достаточно было бы просто точки;
чтобы добавить к этому, доступ к вложенным массивам произойдет так: Итак:
var ourPets = [
{
animalType: "cat",
names: [
"Meowzer",
"Fluffy",
"Kit-Cat"
]
},
{
animalType: "dog",
names: [
"Spot",
"Bowser",
"Frankie"
]
}
];
ourPets[0].names[1]; // Outputs "Fluffy"
ourPets[1].names[0]; // Outputs "Spot"
питонический, рекурсивный и функциональный подход к распутыванию произвольных деревьев JSON:
handlers = {
list: iterate,
dict: delve,
str: emit_li,
float: emit_li,
}
def emit_li(stuff, strong=False):
emission = '<li><strong>%s</strong></li>' if strong else '<li>%s</li>'
print(emission % stuff)
def iterate(a_list):
print('<ul>')
map(unravel, a_list)
print('</ul>')
def delve(a_dict):
print('<ul>')
for key, value in a_dict.items():
emit_li(key, strong=True)
unravel(value)
print('</ul>')
def unravel(structure):
h = handlers[type(structure)]
return h(structure)
unravel(data)
здесь данные - это список python (анализируется из текстовой строки JSON):
data = [
{'data': {'customKey1': 'customValue1',
'customKey2': {'customSubKey1': {'customSubSubKey1': 'keyvalue'}}},
'geometry': {'location': {'lat': 37.3860517, 'lng': -122.0838511},
'viewport': {'northeast': {'lat': 37.4508789,
'lng': -122.0446721},
'southwest': {'lat': 37.3567599,
'lng': -122.1178619}}},
'name': 'Mountain View',
'scope': 'GOOGLE',
'types': ['locality', 'political']}
]
grep jQuery функция позволяет фильтровать через массив:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
$.grep(data.items, function(item) {
if (item.id === 2) {
console.log(item.id); //console id of item
console.log(item.name); //console name of item
console.log(item); //console item object
return item; //returns item object
}
});
// Object {id: 2, name: "bar"}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
на всякий случай, кто посещает этот вопрос в 2017 году или позже и ищем легко запомнить путь, вот подробное сообщение в блоге на доступ к вложенным объектам в JavaScript не будучи обмануты
не удается прочитать свойство " foo " неопределенного
1. Шаблон доступа к вложенным объектам Оливера Стила
самый простой и чистый способ-использовать доступ к вложенным объектам Оливера Стила шаблон
const name = ((user || {}).personalInfo || {}).name;
С этой нотацией вы никогда не столкнетесь с
не удается прочитать свойство " имя " неопределенного.
вы в основном проверяете, существует ли пользователь, если нет, вы создаете пустой объект на лету. Таким образом, ключ следующего уровня будет всегда быть доступны из объекта, который существует или пустой объект, но никогда с неопределенного.
2. Доступ К Вложенным Объектам С Помощью Array Reduce
чтобы иметь доступ вложенные массивы, вы можете написать свой собственный массив снизить утиль.
const getNestedObject = (nestedObj, pathArr) => {
return pathArr.reduce((obj, key) =>
(obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}
// pass in your object structure as array elements
const name = getNestedObject(user, ['personalInfo', 'name']);
// to access nested array, just pass in array index as an element the path array.
const city = getNestedObject(user, ['personalInfo', 'addresses', 0, 'city']);
// this will return the city from the first address item.
существует также отличный тип обработки минимальной библиотеки тыпы что делает все это для вас.
использование lodash было бы хорошим решением
Ex:
var object = { 'a': { 'b': { 'c': 3 } } };
_.get(object, 'a.b.c');
// => 3