중첩된 개체, 어레이 또는 JSON에 액세스하고 처리하는 방법은 무엇입니까?

개체와 배열을 포함하는 중첩된 데이터 구조를 가지고 있습니다.특정 값 또는 여러 값(또는 키)에 액세스하는 등 정보를 추출하려면 어떻게 해야 합니까?

예를 들어 다음과 같습니다.

var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}] }; 

어떻게 하면name의 두 번째 항목의items?



질문에 대한 답변



예단

JavaScript에는 여러 값을 포함할 수 있는 데이터 유형은 하나뿐입니다.오브젝트어레이는 객체의 특수한 형식입니다.

(보통) 오브젝트에는 다음 형식이 있습니다.

{key: value, key: value, ...} 

어레이에는 다음과 같은 특징이 있습니다.

[value, value, ...] 

어레이와 오브젝트 모두key -> value구조.배열의 키는 숫자여야 하지만 개체에서는 모든 문자열을 키로 사용할 수 있습니다.키-값 쌍은 “속성”이라고도 합니다.

속성에는 도트 표기법을 사용하여 액세스할 수 있습니다.

const value = obj.someProperty; 

또는 괄호 표기(속성 이름이 유효한 JavaScript 식별자 이름이 아닌 경우 또는 변수 값인 경우):

// 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을 해석하는 방법은 “Parse JSON in JavaScript?” 질문에 설명되어 있습니다.

추가 읽기 자료

어레이 및 오브젝트에 액세스하는 방법은 JavaScript의 기본 지식이기 때문에 MDN JavaScript 가이드(특히 이 항)를 읽어보시기 바랍니다.



중첩된 데이터 구조 액세스

중첩된 데이터 구조는 다른 배열 또는 객체(즉, 값이 배열 또는 객체)를 참조하는 배열 또는 객체입니다.이러한 구조는 점 또는 괄호 표기법을 연속적으로 적용하여 액세스할 수 있습니다.

다음은 예를 제시하겠습니다.

const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}] }; 

예를 들어, 접속할 필요가 있다고 합시다.name두 번째 항목입니다.

이 작업을 단계적으로 수행하는 방법은 다음과 같습니다.

보다시피data는 객체이기 때문에 도트 표기를 사용하여 해당 속성에 액세스할 수 있습니다.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(foo.bar.baz); // 42 

속성 이름이 동적이고 사전에 모르는 경우에는 어떻게 해야 합니까?

속성 이름을 알 수 없거나 배열의 객체/요소의 모든 속성에 액세스하려면 객체용[MDN] 루프를 사용하고 배열용 루프를 사용하여[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 } 

개체의 출처와 작업에 따라 각 반복에서 속성이 실제로 개체의 속성인지 상속된 속성인지 테스트해야 할 수 있습니다.이 작업은 에서 [MDN]수행할 수 있습니다.

대체 수단으로서for...in와 함께hasOwnProperty를 사용하여[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어레이에 대해 반복하지만 이를 피해야 하는 이유는 다음과 같습니다.JavaScript에서 어레이를 사용하는 ‘for(var item in list)’가 잘못된 관행으로 간주되는 이유는 무엇입니까?

ECMAScript 5의 브라우저 지원이 증가함에 따라 어레이 방식도[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)를 지원하는 환경에서는 어레이뿐만 아니라 반복 가능한 모든 경우에도 사용할[MDN] 수 있는 루프를 사용할 수 있습니다.

for (const item of data.items) {
// `item` is the array element, **not** the index } 

각 반복마다,for...of다음 반복 가능한 요소를 직접 제공하므로 액세스하거나 사용할 “색인”이 없습니다.


데이터 구조의 ‘심도’를 모르는 경우에는 어떻게 해야 합니까?

알 수 없는 키뿐만 아니라 데이터 구조의 “깊이”(즉, 중첩된 개체 수)도 알 수 없습니다.깊이 중첩된 속성에 액세스하는 방법은 일반적으로 정확한 데이터 구조에 따라 달라집니다.

그러나 데이터 구조에 바이너리 트리의 표현과 같은 반복 패턴이 포함되어 있는 경우 솔루션은 일반적으로 데이터 구조의 각 레벨에 재귀적으로 액세스하는 것을 포함합니다.

다음으로 바이너리 트리의 첫 번째 리프 노드를 취득하는 예를 나타냅니다.

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));



도우미

복잡한 오브젝트 또는 어레이의 구조가 반드시 명확하다고는 할 수 없기 때문에 각 단계에서 값을 검사하여 어떻게 더 나아가야 할지 결정하고[MDN][MDN] 이를 수행할 수 있습니다.예를 들어 (Chrome 콘솔 출력):

> console.log(data.items)
[ Object, Object ] 

여기서 알 수 있듯이data.items는 2개의 요소가 모두 오브젝트인 배열입니다.Chrome 콘솔에서는 개체를 즉시 확장하고 검사할 수도 있습니다.

> console.log(data.items[1])
Object
id: 2
name: "bar"
__proto__: Object 

이것은 우리에게 말해준다data.items[1]오브젝트입니다.확장해본 결과, 3개의 특성이 있는 것을 알 수 있습니다.id,name그리고.__proto__후자는 객체의 원형 체인에 사용되는 내부 특성입니다.그러나 원형 체인 및 상속은 이 답변의 범위를 벗어납니다.




이 방법으로 액세스 할 수 있습니다.

data.items[1].name 

또는

data["items"][1]["name"] 

양자는 동등하다.




오브젝트 및 어레이에는 데이터 처리에 도움이 되는 많은 임베디드 메서드가 있습니다.

주의: 대부분의 예에서는 화살표 기능을 사용하고 있습니다.이들은 함수식과 비슷하지만 이 표현은 다음 명령어를 바인드합니다.this어휘적으로 평가하다

Object.keys(), (ES 2017) 및 (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()루프를 위해 파괴적인 임무를 부여받습니다.

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 (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() 그리고

every()메서드 반환true지정된 콜백 함수가 반환되는 경우true어레이의 모든 요소에 대해서요.some()메서드 반환true지정된 콜백 함수가 반환되는 경우true(적어도 1개 이상의) 요소에 대해서요.

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() 그리고

find()methods는 지정된 콜백 함수를 충족하는 첫 번째 요소를 반환합니다.filter()method는 지정된 콜백 함수를 충족하는 모든 요소의 배열을 반환합니다.

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()method는 어레이 요소에서 제공된 콜백 함수를 호출한 결과를 포함하는 어레이를 반환합니다.

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()method는 제공된 콜백 함수를 2개의 요소로 호출함으로써 배열을 단일 값으로 줄입니다.

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()method는 옵션의 두 번째 파라미터(초기값)를 사용합니다.이 기능은 호출하는 어레이가reduce()can에는 0 또는1개의 요소가 있습니다.예를 들어, 함수를 만들고 싶다면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




접속을 시도하고 있는 경우item의 예로부터id또는name어레이 내에서의 위치를 모르는 가장 쉬운 방법은 언더스코어 라이브러리를 사용하는 입니다.

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 

다음은 이 방법을 사용하는 예입니다.