For Of 루프에서 객체 사용


84

for of 루프에서 객체를 사용할 수없는 이유는 무엇입니까? 아니면 브라우저 버그입니까? 이 코드는 Chrome 42에서 작동하지 않으며 undefined는 함수가 아닙니다.

test = { first: "one"}

for(var item of test) {
  console.log(item)
}

테스트는 배열 또는 객체입니까?
Kick Buttowski 2015

9
@KickButtowski, 보이지 않습니까? 확실히 대상입니다.
Green

4
for (let key of Object.keys (test)) {...}
clocksmith

답변:


69

for..of 루프 뿐만 아니라 객체, 배열과 같은 반복 가능한 객체를 지원합니다.

객체의 값을 반복하려면 다음을 사용하십시오.

for (var key in test) {
    var item = test[key];
}

3
@DanielHerr .iterable멤버 함수를 가지고 있는데,이 함수를 가지고 있지 않은 객체에서 사용하려고 할 때 오류가 발생합니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Overv

4
내 말은, 왜 물체에는 그런 것이 없습니까? 기본적으로 추가하면 어떤 문제가 있습니까?
Daniel Herr 2015

3
@DanielHerr 나는 그것에 대한 답이 없습니다. 언어를 디자인하는 사람들에게 물어봐야 할 것입니다.
Overv 2015-04-27

6
@DanielHerr 만약 Object "base class"가 반복 가능하다면, 다른 복잡한 문제들 중에서 Function / Date / etc "subclass"도 마찬가지입니다. 질문 에 대한보다 철저하고 정확한 토론은 esdiscuss.org/topic/es6-iteration-over-object-values#content-5 를 참조하십시오 .
natevw

5
이 for..in 솔루션을 사용하면 여전히 기술적으로 확인해야하지 if (test.hasOwnProperty(key)){ ... }않습니까? 아니면 그게 필요하지 않습니까?
tennisgent

40

다음 구문을 사용할 수 있습니다.

let myObject = {first: "one"};

for(let [key, value] of Object.entries(myObject)) {
    console.log(key, value); // "first", "one"
}

하나, Object.entries 현재 지원이 부족합니다 IE에서 작동하지 않습니다 또는 iOS Safari. 당신은아마 polyfill이 필요할 수 있습니다.


33

키-값 저장소에 데이터를 저장하는 경우 이를 위해 명시 적으로 설계된 것을 사용하십시오Map .

하지만 객체를 사용해야하는 경우 ES2017 (ES8)에서 다음을 사용할 수 있습니다 Object.values.

const foo = { a: 'foo', z: 'bar', m: 'baz' };
for (let value of Object.values(foo)) {
    console.log(value);
}

그는 아직 지원되지 않으면 polyfill을 사용 의 대체 버전을Object.values()

마지막으로이 구문을 지원하지 않는 이전 환경을 지원하는 경우 forEach및 사용에 의존해야합니다 Object.keys.

var obj = { a: 'foo', z: 'bar', m: 'baz' };
Object.keys(obj).forEach(function (prop) {
    var value = obj[prop];
    console.log(value);
});

이를 지원하기 위해 객체 프로토 타입을 확장 할 수 없습니까?
Sonic Soul

1
@SonicSoul : 기술적으로는 그렇습니다.하지만 일반적으로 Object 프로토 타입을 확장하지 않는 것이 좋습니다.
Qantas 94 Heavy

1
Object.entries프로토 타입을 건드리지 않고 폴리 필로 처리 할 수 ​​있습니다.
mpen

5
객체 대신지도를 사용하는 이유는 무엇입니까?
Daniel Herr

1
간단한 것보다 이러한 복잡한 예제를 사용하면 어떤 이점이 for-in있습니까?
1252748

18

ECMAScript 2015 / ES6의 반복자, 반복자 및 for..of 루프

let tempArray = [1,2,3,4,5];

for(element of tempArray) {
  console.log(element);
}

// 1
// 2
// 3
// 4
// 5

하지만 우리가

let tempObj = {a:1, b:2, c:3};

for(element of tempObj) {
   console.log(element);
}
// error

for..of 루프는 Iterables , 즉 Iterator 프로토콜 을 준수 하는 @@ iterator 가있는 객체 에서만 작동 하므로 오류가 발생 합니다 . 즉, 다음 메서드 가있는 객체가 있어야합니다 . next 메소드는 인수를받지 않으며이 두 속성을 가진 객체를 반환해야합니다.

done : 참일 때 시퀀스가 ​​끝났다는 신호, 거짓은 더 많은 값이있을 수 있음을 의미합니다. value : 시퀀스의 현재 항목입니다.

따라서 for..of 와 함께 작동 하는 객체를 Iterable 로 만들려면 다음을 수행 할 수 있습니다.

1. 신비로운 @@ iterator를 할당 하여 객체를 Iterable 로 만듭니다. Symbol.iterator 속성을 통해 속성 만듭니다 . 방법은 다음과 같습니다.

let tempObj = {a:1, b:2, c:3};

tempObj[Symbol.iterator]= () => ({
next: function next () {
return {
    done: Object.keys(this).length === 0,
    value: Object.keys(this).shift()
     }
    }
  })

for(key in tempObj){
 console.log(key)
}
// a
// b
// c

2. Object.entries 를 사용하면 Iterable .

let tempObj = {a:1, b:2, c:3};

for(let [key, value] of Object.entries(tempObj)) {
    console.log(key, value);
}
// a 1
// b 2
// c 3

3. 사용 Object.keys 사용 , 방법은 다음과 같습니다.

let tempObj = {a:1, b:2, c:3};
for (let key of Object.keys(tempObj)) {
    console.log(key);
}

// a
// b
// c

도움이 되었기를 바랍니다!!!!!!


16

이 코드로 객체를 반복 가능하게 만들었습니다.

Object.prototype[Symbol.iterator] = function*() {
 for(let key of Object.keys(this)) {
  yield([ key, this[key] ])
} }

용법:

for(let [ key, value ] of {}) { }

대안 :

for(let [ key, value ] of Object.entries({})) { }

48
이것이 허용되는 솔루션 인 이유를 모릅니다. 폴리 필이 아닌 경우 프로토 타입을 수정하는 것은 항상 끔찍한 아이디어입니다.
user1703761

2
@ user1703761 작동하기 때문에 허용되는 솔루션입니다. 이것이 그렇게 끔찍한 경우 어떤 문제가 발생할지 설명하십시오.
Daniel Herr

9
모든 종류의 문제, 주로 순방향 호환성 문제가 있습니다. 한 가지 예는 이전에 이름이었던 Array.prototype.includes에 포함되어 있지만 Moo Tools가 프로토 타입을 확장하고 구현이 호환되지 않는 경우입니다. bugzilla.mozilla.org/show_bug.cgi?id=1075059를 참조하십시오 . Prototype 라이브러리 desaster도 찾아보십시오.)
user1703761

4
반복기가 개체에 추가되면이를 덮어 쓰고 반복기가 개체 하위 유형에 추가되면 하위 유형 반복기를 사용하므로 앞으로 호환성 문제가 발생하지 않을 것이라고 생각합니다.
Daniel Herr

4
여러분, 프로토 타입을 수정하는 것은 나쁜 생각입니다 !!! 실제로 질문에 답한 OP를 부끄럽게합시다!
NiCk Newman

12

객체 리터럴에는 Symbol.iterator 속성 이 없기 때문 입니다. 구체적으로, 당신은 할 수 있습니다 만 반복 처리를 통해 문자열 , 배열 , 지도 , 설정 , 인수 , NodeList를 (하지 널리 지원) 및 발전기용의 루프.

Object Literal 반복을 처리하기 위해 두 가지 옵션이 있습니다.

...에서

for(let key in obj){
    console.log(obj[key]); 
}

Object.keys + forEach

Object.keys(obj).forEach(function(key){
    console.log(obj[key]);
});

3

대답은 아니요입니다. For..Of를 Object 리터럴과 함께 사용할 수 없습니다.

For..Of는 이터 러블 전용이라는 Overv에 동의합니다. for..in으로 키와 값을 반복하기 위해 Objects를 사용하기 때문에 똑같은 질문이있었습니다. 그러나 나는 그것이 ES6 MAPSSETS 의 목적이라는 것을 깨달았습니다 .

let test = new Map();
test.set('first', "one");
test.set('second', "two");

for(var item of test) {
  console.log(item); // "one" "two"
}

따라서 for..In ( hasOwnProperty로 유효성 검사)을 사용할 필요가 없다는 목표를 달성합니다. )을 사용할 필요가없고 Object.keys ()를 사용할 필요가 없다는 .

또한 키는 문자열로 제한되지 않습니다. 숫자, 개체 또는 기타 리터럴을 사용할 수 있습니다.


2

개체 리터럴에는 for...of루프 작업에 필요한 기본 제공 반복기가 없습니다 . 그러나 [Symbol.iterator]개체에 자신 을 추가하는 문제를 겪고 싶지 않다면 간단하게 Object.keys()방법을 사용할 수 있습니다 . 이 메서드는 Array이미 내장 된 반복기가 있는 객체를 반환 하므로 다음과 같은 for...of루프와 함께 사용할 수 있습니다 .

const myObject = {
    country: "Canada",
    province: "Quebec",
    city: "Montreal"
}

for (let i of Object.keys(myObject)) {
    console.log("Key:", i, "| Value:", myObject[i]);
}

//Key: country | Value: Canada
//Key: province | Value: Quebec
//Key: city | Value: Montreal

매번 키를 사용하는 것은 반복자를 한 번 추가하는 것보다 더 어렵습니다. 또한 Object.keys ()는 ES5입니다.
Daniel Herr

1

주어진 객체에 대해 반복자를 정의 할 수 있습니다. 이렇게하면 각 객체에 대해 다른 논리를 넣을 수 있습니다.

var x = { a: 1, b: 2, c: 3 }
x[Symbol.iterator] = function* (){
    yield 1;
    yield 'foo';
    yield 'last'
}

그런 다음 직접 반복하십시오. x

for (let i in x){
    console.log(i);
}
//1
//foo
//last

Object.prototype객체 에 대해 동일한 작업을 수행하고 모든 객체에 대한 일반 반복자를 가질 수 있습니다.

Object.prototype[Symbol.iterator] = function*() {
    for(let key of Object.keys(this)) {
         yield key 
    } 
 }

그런 다음 객체를 다음과 같이 반복하십시오.

var t = {a :'foo', b : 'bar'}
for(let i of t){
    console.log(t[i]);
}

아니면 이렇게

var it = t[Symbol.iterator](), p;
while(p = it.next().value){
    console.log(t[p])
}

1

나는 내 물건을 쉽게 위로하기 위해 다음을 수행했습니다.

for (let key in obj) {
  if(obj.hasOwnProperty(key){
    console.log(`${key}: ${obj[key]}`);
  }
}


0

사용은 어떻습니까

function* entries(obj) {
    for (let key of Object.keys(obj)) {
        yield [key, obj[key]];
    }
}

for ([key, value] of entries({a: "1", b: "2"})) {
    console.log(key + " " + value);
}

0

ES6에서는 생성기를 사용할 수 있습니다.

var obj = {1: 'a', 2: 'b'};

function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}

let generator = entries(obj);

let step1 = generator.next();
let step2 = generator.next();
let step3 = generator.next();

console.log(JSON.stringify(step1)); // {"value":["1","a"],"done":false}
console.log(JSON.stringify(step2)); // {"value":["2","b"],"done":false}
console.log(JSON.stringify(step3)); // {"done":true}

다음은 jsfiddle입니다. 출력에서 "value""done"키 가있는 객체를 얻을 수 있습니다. "Value"당신이 모든 것을 포함 그것을 가지고 및 "done"부울의 반복의 현재 상태입니다.


0

배열 파괴를 사용하면 다음과 같이 반복 할 수 있습니다. forEach

const obj = { a: 5, b: 7, c: 9 };

Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.