JavaScript 객체를 반복하거나 열거하는 방법


2877

다음과 같은 JavaScript 객체가 있습니다.

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

지금은 모든을 통해 루프를 원하는 p요소 ( p1, p2, p3...) 그리고 자신의 키와 값을 얻는다. 어떻게해야합니까?

필요한 경우 JavaScript 객체를 수정할 수 있습니다. 내 궁극적 인 목표는 일부 키 값 쌍을 반복하는 것이며 가능한 경우을 사용하지 않기를 원합니다 eval.


9
객체 리터럴과 JSON의 혼동을 피하기 위해 JSON을 JavaScript (객체)로 변경했습니다.
Felix Kling

답변:


4365

for-in다른 사람들이 보여주는 것처럼 루프를 사용할 수 있습니다 . 그러나 얻는 키가 객체의 실제 속성이며 프로토 타입에서 가져 오지 않았는지 확인해야합니다.

스 니펫은 다음과 같습니다.

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

Object.keys () 대안으로 :

var p = {
    0: "value1",
    "b": "value2",
    key: "value3"
};

for (var key of Object.keys(p)) {
    console.log(key + " -> " + p[key])
}

사용주의 for-of대신을 for-in, 그것은 명명 된 속성에 정의되지 않은, 그리고 반환됩니다 사용하지 않을 경우 Object.keys()전체 프로토 타입 체인 특성없이 개체 만의 고유 속성의 사용을 보장합니다

새로운 Object.entries()방법 사용 하기 :

참고 : 이 방법은 Internet Explorer에서 기본적으로 지원되지 않습니다. 구형 브라우저에는 Polyfill 사용을 고려할 수 있습니다.

const p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (let [key, value] of Object.entries(p)) {
  console.log(`${key}: ${value}`);
}

34
명확성을 위해 경고 줄을 다음과 같이 변경하라고 제안 하시겠습니까?alert(key + " -> " + JSON.stringify(p[key]));
Steve Midgley

80
hasOwnProperty의 필요성을 설명 할 수 있습니까? 프로토 타입의 의미는 무엇입니까?
kamaci

331
자바 스크립트에서 모든 객체에는 메타 정보가있는 많은 내장 키-값 쌍이 있습니다. 객체의 모든 키-값 쌍을 반복하면 반복됩니다. hasOwnPropery ()는 이것을 걸러냅니다.
danieltalsky

57
실제로 For ... in 은 더 이상 사용되지 않습니다. 각각의 ...에 있습니다. 하지만 저는 고고학자 라는 용어를 정말 좋아합니다 . 나는 그것을 사용하기 시작해야합니다.
Ben Y

17
자바 스크립트의 각 객체 (실제로 키-값 쌍)에는 __proto__또는 속성이 prototype있습니다. 이 속성에는 부모 개체에 대한 참조가 있습니다. 객체는 부모로부터 자동으로 속성을 상속받습니다. hasOwnProperty이것이을 사용하는 이유인데 , 이는 우리가 부모가 아닌 객체 자체의 속성에 관심이 있음을 나타냅니다.
Zubair Alam

1104

인 ECMAScript 5에서, 당신은 결합 할 수 Object.keys()Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };

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

ECMAScript 6는 for...of다음을 추가합니다 .

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ECMAScript 8 Object.entries()은 원본 객체에서 각 값을 조회 할 필요가없는 기능을 추가 합니다.

Object.entries(obj).forEach(
    ([key, value]) => console.log(key, value)
);

for...of, destructuring 및을 결합 할 수 있습니다 Object.entries.

for (const [key, value] of Object.entries(obj)) {
    console.log(key, value);
}

모두 Object.keys()Object.entries()A와 같은 순서로 반복 처리 특성 for...in루프 하지만 프로토 타입 체인을 무시 . 객체 자체의 열거 가능한 속성 만 반복됩니다.


21
왜 표준이 제공하지 않았 Object.forEach(obj, function (value, key) {...})습니까? :( 물론 obj.forEach(function...)짧아지고 보완 적이 Array.prototype.forEach지만 객체가 자신의 forEach속성을 정의하게 할 위험이 있습니다 . 나는 Object.keys객체 키를 수정하는 콜백에 대해 경비원을 원한다고 가정 합니다.
David Harkness

7
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
David Harkness

7
@DavidHarkness ES2017에는 Object.entries가 있습니다. 거기에서 다음을 수행 할 수 있습니다. Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([키, 값]은 두 항목 모두에 직접 액세스하기 위해 배열을 파괴합니다. 추가 매개 변수로 매개 변수를 랩해야합니다.)
Andreas Linnert

indexjson에서 키를 어떻게 얻 습니까? 또는 필요한 경우 별도의 카운터를 사용해야합니까?
Saravanabalagi Ramachandran

3
for...ofES2016이 아닌 ES6 표준입니다.
Rax Weber

342

for-in 루프 를 사용해야합니다

그러나 이런 종류의 루프 를 사용할 때는 프로토 타입 체인을 따라 모든 속성을 반복 하기 때문에 매우주의 해야합니다 .

따라서 for-in 루프를 사용할 때는 항상 hasOwnProperty메서드를 사용 하여 반복의 현재 속성이 실제로 확인하려는 객체의 속성인지 확인하십시오.

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}

31
이것은 메인 로직이 두 개가 아닌 하나의 중첩 루프 일 수 있기 때문에 levik의 솔루션보다 낫습니다. 코드를보다 쉽게 ​​읽을 수 있습니다. 계속 주위의 괄호를 풀었지만 그들은 불필요하다.
SystemicPlural

52
그것이 없으면 그것이 무엇이고 무엇이 아닌지를 조금 불분명하게 { }하기 때문에 나는 개인적으로 제거 하지 않을 것입니다. 그러나 나는 그것이 단지 의견의 문제라고 생각합니다 :)ifif
pimvdb

34
예, { }나중에 if스코프 에 무언가를 추가 해야하는 경우 혼란을 피하기 위해 주로 유지하는 것이 좋습니다.
Andreas Grech

8
이전 의견을 읽었을 때 나는 "범위"라고 말했기 때문에 올바른 용어를 사용하지 않았다는 것을 깨달았습니다. 그러나 JavaScript에는 기능 범위 만 있습니다. 제가 실제로 의미 한 것은 "if block"이었습니다.
Andreas Grech

1
eomeroff, 만약 당신이 정말로 그것에 대해 걱정한다면, 당신은 항상 다음과 같은 것을 할 수 있습니다 : Object.prototype.hasOwnProperty.call(p, prop) 그러나 이것도 Object.prototype에 대한 조작으로부터 보호 할 수 없습니다 ...
jordancpaul

252

객체를 반복하는 대체 방법에 대해 언급하지 않으면 질문이 완료되지 않습니다.

오늘날 많은 잘 알려진 JavaScript 라이브러리는 컬렉션, 즉 배열 , 객체배열과 유사한 객체 를 반복하는 고유 한 메소드를 제공 합니다 . 이 방법은 사용하기 편리하며 모든 브라우저와 완전히 호환됩니다.

  1. jQuery로 작업하는 경우 jQuery.each()method를 사용할 수 있습니다 . 객체와 배열을 완벽하게 반복하는 데 사용할 수 있습니다.

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  2. 에서 Underscore.js 당신은 방법을 찾을 수 있습니다 _.each()제공된 기능에 차례로 각각 산출 요소의 목록을 반복 할 때, (에서 인수의 순서에주의 iteratee의 기능을!)

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
  3. Lo-Dash 는 객체 속성을 반복하는 몇 가지 방법을 제공합니다. 기본 _.forEach()(또는 별명 _.each())은 객체와 배열을 반복하는 데 유용하지만 (!) length속성이있는 객체 는 배열처럼 취급 되며이 동작을 피하기 위해 사용 _.forIn()_.forOwn()메서드를 제안 합니다 (이들도 value먼저 인수가 있음).

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });

    _.forIn()을 반복 자신의 상속 객체의 열거 속성, 동안 _.forOwn()반복 만 이상 자신의 객체의 속성 (기본적으로에 대해 확인 hasOwnProperty기능). 간단한 객체와 객체 리터럴의 경우 이러한 방법 중 하나가 잘 작동합니다.

일반적으로 설명 된 모든 메소드는 제공된 오브젝트와 동일한 동작을 갖습니다. 기본 for..in루프를 사용하는 것 외에도 일반적으로 와 같은 추상화보다 빠릅니다jQuery.each() . 이러한 방법은 사용하기가 훨씬 쉽고 코딩이 덜 필요하며 오류 처리 기능이 향상됩니다.


4
값을 얻으려면 $ .each (obj, function (key, value) {console.log (value.title);});
Ravi Ram

2
그냥 재미 방법 밑줄 및 JQuery와 변경된 매개 변수 :
ppasler

52

ECMAScript 5에서는 리터럴의 반복 필드에 새로운 접근 방식이 있습니다. Object.keys

MDN에서 볼 수있는 추가 정보

아래는 현재 버전의 브라우저 (Chrome30, IE10, FF25)에서 더 빠른 솔루션입니다.

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

이 접근법의 성능을 jsperf.com의 다른 구현과 비교할 수 있습니다 .

Kangax의 compat 테이블에서 볼 수있는 브라우저 지원

오래된 브라우저의 경우 간단 하고 완전한 폴리 필이 있습니다

UPD :

이 질문에서 가장 인기있는 모든 경우에 대한 성능 비교 perfjs.info:

객체 리터럴 반복


실제로, 나는이 방법을 게시하고 싶었습니다. 하지만 당신은 나를 이겼습니다 :(
Jamie Hutber

50

머리말:

  • 객체 속성은 소유 하거나 (속성이 객체 자체에 있음) 상속 될 수 있습니다. 아닌 프로토 타입 중 하나).
  • 객체 속성은 열거 가능 또는 열거 불가능 . 열거 할 수없는 속성은 많은 속성 열거 / 배열에서 제외됩니다.
  • 속성 이름은 문자열 또는 기호 일 수 있습니다. 이름이 Symbol 인 속성은 많은 속성 열거 / 배열에서 제외됩니다.

2018 년에는 객체의 속성을 반복하는 옵션이 있습니다 (일부 예제는 목록을 따릅니다).

  1. for-in[ MDN , spec ] — 상속 된 속성 (이름이 문자열 인 속성 포함)을 포함 하여 객체의 열거 가능한 속성 이름을 반복하는 루프 구조
  2. Object.keys[ MDN , spec ] — 이름이 문자열 인 객체 자체열거 가능한 속성의 이름 배열을 제공하는 함수 입니다.
  3. Object.values[ MDN , 사양 ] - 함수는 배열 제공 객체의의 고유의 , 열거 속성.
  4. Object.entries[ MDN , spec ] — 객체 자체열거 가능한 속성 의 이름 값 배열을 제공하는 함수입니다 (배열의 각 항목은 배열입니다 ).[name, value]
  5. Object.getOwnPropertyNames[ MDN , spec ] — 이름이 문자열 인 객체 자체 속성 (열거 불가능한 속성) 의 이름 배열을 제공하는 함수 입니다.
  6. Object.getOwnPropertySymbols[ MDN , spec ] — 이름이 Symbols 인 객체 자체 속성 (열거 불가능한 속성) 의 이름 배열을 제공하는 함수 입니다.
  7. Reflect.ownKeys[ MDN , 사양 ] - 객체의 이름의 배열을 제공하는 기능을 스스로 그 이름 문자열 또는 기호 여부 속성 (심지어 비 열거 것들).
  8. 당신이 원하는 경우 모든 비 열거 상속 포함한 객체의 속성,의를, 당신은 루프를 사용할 필요가 Object.getPrototypeOf[ MDN , 사양 ] 및 사용 Object.getOwnPropertyNames, Object.getOwnPropertySymbols또는 Reflect.ownKeys(이 답변의 하단에있는 예) 각각의 프로토 타입 체인에있는 객체.

그들 모두 제외와 함께 for-in, 당신은 (배열에 구조를 루핑 어떤 종류의 사용하십시오 for, for-of, forEach, 등).

예 :

for-in:

Object.keys ( for-of루프를 사용하지만 모든 루핑 구문을 사용할 수 있습니다) :

Object.values:

Object.entries:

Object.getOwnPropertyNames:

Object.getOwnPropertySymbols:

Reflect.ownKeys:

상속 불가능한 속성 을 포함한 모든 속성 :


열거 가능하거나 숫자를 지정할 수없는 객체 속성이 추가되었습니다.
serraosays

49

다음과 같이 반복 할 수 있습니다.

for (var key in p) {
  alert(p[key]);
}

참고 key속성 값에 적용되지 않습니다, 그냥 인덱스 값입니다.


13
이것은 반복되며 완전히 정확하지는 않습니다. 이 작업을 제대로 수행하려면 hasOwnProperty를 확인해야합니다
Vatsal

4
나는이 답변이 먼저 온다는 것을 깨달을 때까지 위의 의견에 근거하여 이것을 처음으로 하향 조정 하였으므로 "반복되지 않는다". 불완전하지만 많은 경우에 잘 작동합니다.
billynoah

27

es2015가 점점 인기를 얻고 있기 때문에 생성기와 반복자를 사용하여 [key, value]쌍 을 원활하게 반복하는이 답변을 게시하고 있습니다. 다른 언어에서도 가능합니다 (예 : Ruby).

여기 코드가 있습니다.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function* () {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};

for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

반복자 및 생성기를 수행하는 방법에 대한 모든 정보는 개발자 Mozilla 페이지에서 찾을 수 있습니다.

희망 누군가를 도왔습니다.

편집하다:

ES2017에는 객체에서 쌍을 Object.entries반복하는 [key, value]것이 훨씬 쉬워집니다. TS39 에 따라 표준의 일부가 될 것으로 알려져 있습니다. 스테이지 정보 .

나는 지금보다 더 신선 해지도록 내 대답을 업데이트해야 할 때라고 생각합니다.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

MDN 페이지에서 사용법에 대한 자세한 내용을 볼 수 있습니다


이것은 나에게 불필요하고 불필요하게 보입니다. 시스템의 모든 객체에 추가 하시겠습니까? 반복자를 제공하는 것이`for (const [k, v] of myObject) '를 수행 할 수 있다고 생각했습니다. 약간의 추가 가치를 제공하는 추가 코드처럼 보입니다.
Dean Radcliffe

22
for(key in p) {
  alert( p[key] );
}

참고 : 배열을 통해이 작업을 수행 할 수 있지만 length및 다른 속성도 반복합니다 .


4
이와 같은 for 루프를 사용할 때 key인덱스 값만 사용하므로 0, 1, 2 등 만 경고합니다. p [key]에 액세스해야합니다.
Bryan

1
JavaScript에서 가장 느린 배열 반복 방법입니다. 컴퓨터에서 이것을 확인할 수 있습니다
-JavaScript

5
@ Pencroff : 문제는 문제가 배열을 반복하는 것에 관한 것이 아니라는 것입니다 ...;)
Sk8erPeter

이것은 내가 stackoverflow에서 이해하지 못하는 것입니다. 리차드는 정답을했으며 그 답변을 가장 먼저 받았지만 +1을 얻지 못했습니까? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }이 경고에 "p1"과 "p2"를 표시하고 있습니다.
Sebastian

5
가장 큰 차이점은 품질이라고 생각합니다. 다른 답변은 방법뿐만 아니라 경고 (예 : 프로토 타입)와 해당 경고를 처리하는 방법도 알려줍니다. IMHO, 다른 답변 내 것보다 낫습니다 :).
Richard Levasseur

20

여기에있는 모든 답변을 살펴본 후 내 json 객체가 깨끗하기 때문에 hasOwnProperty가 필요하지 않습니다. 추가 자바 스크립트 처리를 추가하는 것은 의미가 없습니다. 이것이 내가 사용하는 전부입니다.

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}

18
JSON 객체가 깨끗한 지 여부는 관련이 없습니다. 다른 코드에서 속성을 on으로 설정하면에 Object.prototype의해 열거됩니다 for..in. 그렇게하는 라이브러리를 사용하고 있지 않다면을 호출 할 필요가 없습니다 hasOwnProperty.
G-Wiz

4
로 만든 경우 완전히 청소 될 수있다Object.create(null)
후안 멘데스

20

프로토 타입 체인 속성을 건너 뛰어야하는 forEach ()가 있는 프로토 타입 을 통해 :

Object.prototype.each = function(f) {
    var obj = this
    Object.keys(obj).forEach( function(key) { 
        f( key , obj[key] ) 
    });
}


//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3

2
프로토 타입에주의하십시오 : obj = { print: 1, each: 2, word: 3 }produce TypeError: number is not a function. 사용하여 forEach유사한 일치하도록 Array기능하는 것은 다소 위험을 줄일 수 있습니다.
David Harkness

18

그것은 이러한 답변에 흥미있는 사람들이 모두 감동했다입니다 Object.keys()for...of하지만 그들을 결합하지 :

var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
    console.log(key + ':' + map[key]);

당신은 단지 수 이 반복자 아니기 때문에, 그리고 나 오링은 추악한 / 비효율적이다. 나는 대부분의 사람들이 (확인 여부에 관계없이 ) 자제 하지 않기 때문에 기쁘다. 왜냐하면 위의 대답 외에는 대답하기 위해 여기에있다.for...ofObjectfor...index.forEach()Object.keys()
for...in.hasOwnProperty()


일반적인 객체 연결을 반복 할 수 있습니다! Mapfor...ofChrome 및 FF에서 작동 하는 멋진
DEMO 를 직접 사용하는 것처럼 작동합니다 (ES6 만 가정합니다)

var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
    //key:value
    console.log(pair[0] + ':' + pair[1]);

//or
for (let [key, value] of ordinaryObject)
    console.log(key + ':' + value);

아래에 심을 포함시키는 한 :

//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
    var keys = Object.keys(this)[Symbol.iterator]();
    var obj = this;
    var output;
    return {next:function() {
        if (!(output = keys.next()).done)
            output.value = [output.value, obj[output.value]];
        return output;
    }};
};

좋은 구문 설탕이없는 실제 Map 객체를 만들 필요가 없습니다.

var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
    console.log(pair[0] + ':' + pair[1]);

사실,이 심으로, 당신이 여전히 맵의 다른 기능을 활용하고 싶었지만 (모두 숨기지 않고) 여전히 깔끔한 객체 표기법을 사용하고 싶었다면, 객체는 이제 반복 가능하기 때문에 이제 맵을 만들 수 있습니다!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

shim을 좋아하지 않거나 prototype일반적으로 혼란스러워하는 사람들은 창에서 대신 getObjIterator()다음 과 같이 호출하여 기능을 자유롭게 만드십시오 .

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();

    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;

        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    return iterator;
}

이제는 일반 함수로 호출 할 수 있습니다. 다른 영향은 없습니다.

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

또는

for (let pair of getObjIterator(ordinaryObject))

그것이 효과가없는 이유는 없습니다.

미래에 오신 것을 환영합니다.


1
케이스 포인트 . 사람들이 아래로 스크롤하여 도움이되는 한, 그것이 전부입니다. 일반적으로 온라인에서 보는 것을 좋아하지 않고 무언가를 시도하고 그것을 알아 낸 다음 다시 공유하려고합니다. 그것은 좋은 도코입니다. 내가 완전히 잊어 버린 것들을 검색하기 전에 실제로 내 대답을 보았습니다!
Hashbrown

@HelpMeStackOverflowMyOnlyHope 개인적으로 나는 내가 정의하지 않은 객체의 프로토 타입을 수정하는 것을 좋아하지 않습니다.
야누스 트롤 슨

@JanusTroelsen 전체 답변을 읽었습니까? For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then;
Hashbrown

이 기술은 일반 객체에서는 작동하지 않지만 그럼에도 유용합니다.
noɥʇʎԀʎzɐɹƆ

그것은 평범한 객체, 말 그대로 요점에서 ordinaryObject작동합니다 (마법이 여전히 그 유형에 대해 작동한다는 강조 와 같은 변수 이름 ). 데모를 확인 했습니까? @ noɥʇʎԀʎzɐɹƆ 당신을 위해 작동하지 않는 것은 무엇입니까? (SE 프로필 이미지가 보스 인 PS)
Hashbrown 2016 년

13

Object.keys (obj) : 배열

열거 가능한 모든 고유 한 (상속되지 않은) 속성의 모든 문자열 값 키를 검색합니다.

따라서 hasOwnProperty로 각 객체 키를 테스트하여 원하는 키 목록을 제공합니다. 추가 테스트 작업이 필요하지 않으며 Object.keys( obj ).forEach(function( key ){})더 빨라야합니다. 그것을 증명합시다 :

var uniqid = function(){
			var text = "",
					i = 0,
					possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			for( ; i < 32; i++ ) {
					text += possible.charAt( Math.floor( Math.random() * possible.length ) );
			}
			return text;
		}, 
		CYCLES = 100000,
		obj = {}, 
		p1,
		p2,
		p3,
		key;

// Populate object with random properties
Array.apply( null, Array( CYCLES ) ).forEach(function(){
	obj[ uniqid() ] = new Date()
});

// Approach #1
p1 = performance.now();
Object.keys( obj ).forEach(function( key ){
	var waste = obj[ key ];
});

p2 = performance.now();
console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds.");

// Approach #2
for( key in obj ) {
	if ( obj.hasOwnProperty( key ) ) {
		var waste = obj[ key ];
	}
}

p3 = performance.now();
console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds.");

내 Firefox에서 다음과 같은 결과가 있습니다

  • Object.keys 접근에는 40.21101451665163 밀리 초가 걸렸습니다.
  • for ... in / hasOwnProperty 접근 방식에 98.26163508463651 밀리 초가 걸렸습니다.

추신. 크롬에서 더 큰 차이 http://codepen.io/dsheiko/pen/JdrqXa

PS2 : ES6 (EcmaScript 2015)에서는 반복 가능한 객체를 더 잘 반복 할 수 있습니다.

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
    console.log(pair);
}

// OR 
let map = new Map([
    [false, 'no'],
    [true,  'yes'],
]);
map.forEach((value, key) => {
    console.log(key, value);
});


{} 표기법을 사용 of 하지Map
Hashbrown

13

다음은 객체를 반복하는 다른 방법입니다.

   var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};


Object.keys(p).forEach(key => { console.log(key, p[key]) })


3
이것은 매우 멋지지만 큰 객체의 경우 for방법이 더 효과적 일 수 있습니다.
Rolf

13

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " = " + p[key]);
    }
}
<p>
  Output:<br>
  p1 = values1<br>
  p2 = values2<br>
  p3 = values3
</p>


12

Object.keys ()를 사용하여 아래와 같이 객체 키를 반복하여 값을 얻을 수도 있습니다.

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});


당신은 내 시간을 절약, 감사합니다
스왑

알아두면 좋은 점 :)
Onera

8

의존성이없는 JavaScript 코드 만 :

var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
keys = Object.keys(p);   // ["p1", "p2", "p3"]

for(i = 0; i < keys.length; i++){
  console.log(keys[i] + "=" + p[keys[i]]);   // p1=value1, p2=value2, p3=value3
}

8

Object.keys()메소드는 주어진 객체 자체의 열거 가능한 속성의 배열을 반환합니다. 자세한 내용은 여기를 참조 하십시오

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))


8

공연

오늘 2020.03.06 MacOs High Sierra v10.13.6에서 Chrome v80.0, Safari v13.0.5 및 Firefox 73.0.1에서 선택한 솔루션의 테스트를 수행합니다.

결론

  • for-in(A, B) 기반 솔루션 은 크고 작은 객체의 모든 브라우저에서 빠르거나 빠릅니다.
  • 놀랍게도 for-of(H) 솔루션은 작고 큰 물체를 위해 크롬에서 빠릅니다.
  • 명시 적 색인을 기반으로하는 솔루션 i (J, K) 은 작은 객체의 모든 브라우저에서 매우 빠릅니다 (Firefox의 경우 큰 객체에서는 빠르지 만 다른 브라우저에서는 보통 빠름)
  • 반복자 (D, E) 기반 솔루션이 가장 느리고 권장되지 않습니다.
  • 솔루션 C는 큰 물체의 경우 느리고 작은 물체의 경우 중간 느립니다.

여기에 이미지 설명을 입력하십시오

세부

성능 테스트가 수행되었습니다

  • 3 개의 필드가있는 작은 물체- 여기 에서 기계를 테스트 할 수 있습니다.
  • 1000 개의 필드가있는 '큰'개체- 여기 에서 컴퓨터에서 테스트를 수행 할 수 있습니다.

아래의 스 니펫은 사용 된 솔루션을 나타냅니다.

그리고 여기 크롬의 작은 물체에 대한 결과가 있습니다.

여기에 이미지 설명을 입력하십시오


7

모든 객체에 간단한 forEach 함수를 추가 할 수 있으므로 모든 객체를 자동으로 반복 할 수 있습니다.

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        for (var key in this) {
            if (!this.hasOwnProperty(key)) {
                // skip loop if the property is from prototype
                continue;
            }
            var value = this[key];
            func(key, value);
        }
    },
    enumerable: false
});

"-방법에서" for ... 를 좋아하지 않는 사람들을 위해 :

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        var arr = Object.keys(this);
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i];
            func(key, this[key]);
        }
    },
    enumerable: false
});

이제 간단하게 전화를 걸 수 있습니다.

p.forEach (function(key, value){
    console.log ("Key: " + key);
    console.log ("Value: " + value);
});

다른 forEach-Methods와 충돌하지 않으려면 고유 한 이름으로 이름을 지정할 수 있습니다.


3
같은 내장 객체의 프로토 타입을 수정하는 Object것은 다른 코드와 쉽게 충돌 할 수 있기 때문에 일반적으로 안티 패턴으로 간주됩니다. 상처는 이런 식으로 하지 않는 것이 좋습니다.
Moritz

6

순수한 JavaScript를 사용할 때 루프는 꽤 흥미로울 수 있습니다. ECMA6 (New 2015 JavaScript 사양)만이 루프를 제어하고있는 것으로 보입니다. 불행히도이 글을 쓰는 동안 브라우저와 널리 사용되는 통합 개발 환경 (IDE)은 여전히 ​​새로운 종과 휘파람을 완전히 지원하기 위해 고군분투하고 있습니다.

ECMA6 이전의 JavaScript 객체 루프는 다음과 같습니다.

for (var key in object) {
  if (p.hasOwnProperty(key)) {
    var value = object[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
  }
}

또한, 이것은이 질문의 범위를 벗어난 것을 알고 있지만 2011 년 ECMAScript 5.1은 forEach기본적으로 배열을 반복하는 새로운 개선 된 방법을 만들면서 반복 할 수없는 객체를 이전의 장황하고 혼란스러운 for루프로 남겨 두는 배열 방법 만 추가했습니다 . 그러나 이상한 점은이 새로운 forEach방법이 break모든 종류의 다른 문제를 야기하는 지원하지 않는다는 것입니다.

기본적으로 2011 년에는 많은 인기있는 라이브러리 (jQuery, Underscore 등)가 다시 구현하기로 결정한 것 이외의 JavaScript를 반복하는 확실한 방법이 없습니다.

2015 년 현재 모든 객체 유형 (배열 및 문자열 포함)을 루프 (및 중단)하는 방법이 개선되었습니다. 권장 사항이 주류가 될 때 JavaScript의 루프는 다음과 같습니다.

for (let [key, value] of Object.entries(object)) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

대부분의 브라우저는 2016 년 6 월 18 일 현재 위의 코드를 지원하지 않습니다. Chrome에서도 작동하려면이 특수 플래그를 활성화해야합니다. chrome://flags/#enable-javascript-harmony

이것이 새로운 표준이 될 때까지 기존 방법을 계속 사용할 수 있지만 인기있는 라이브러리의 대안 이나 이러한 라이브러리를 사용하지 않는 사람들을위한 간단한 대안 도 있습니다.


이 작업의 바이올린을 제공 할 수 있습니까? 여기 내 시도가 있습니다. jsfiddle.net/abalter/sceeb211
abalter

@abalter 죄송합니다. 내 코드에 오타가 있음을 깨달았습니다. 나는 그것을 고치고 여기에서 JsFiddle을 업데이트했다 : jsfiddle.net/sceeb211/2
Nicolas Bouvrette

나는 크롬에 있고 점점 Uncaught TypeError: Object.entries is not a function. 아직 크롬으로 구현되지 않았습니까?
abalter

@abalter입니다. Chrome 버전 51이 있고 편집 및 Jsfiddle 의견에 설명 된대로 플래그를 사용하도록 설정했는지 확인하십시오. 자세한 내용은 여기에서 확인할 수 있습니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nicolas Bouvrette 2016 년

미안하지만 그 플래그에 대해 그리워했습니다. 아직 완전히 구현 된 기능이 아님을 알았습니다.
abalter 2016 년

5

ES6에는 이전에 내부 메소드를 노출하는 잘 알려진 기호가 있으며,이 기호를 사용하여이 객체에서 반복자가 작동하는 방식을 정의 할 수 있습니다.

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3",
    *[Symbol.iterator]() {
        yield *Object.keys(this);
    }
};

[...p] //["p1", "p2", "p3"]

이것은 for ... in es6 루프를 사용하는 것과 동일한 결과를 제공합니다.

for(var key in p) {
    console.log(key);
}

그러나 이제 es6을 사용하는 기능을 아는 것이 중요합니다!


1
커스텀 객체 반복자는 Object.keys()메모리에 의해 생성되고 메모리에 할당 된 배열의 내장 배열 반복자를 호출합니다 ... Cool!
ooo

5

obj.hasOwnerProperty모든 for ... in루프 내에서 확인하는 대신이 작업을 수행합니다 .

var obj = {a : 1};
for(var key in obj){
    //obj.hasOwnProperty(key) is not needed.
    console.log(key);
}
//then check if anybody has messed the native object. Put this code at the end of the page.
for(var key in Object){
    throw new Error("Please don't extend the native object");
}

5

    var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
{"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
for(var value in p) {
    for (var key in value) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }
}


json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -> " + json[i][key]); } } }
Marek Bernád

5

사용 for-of에를Object.keys()

처럼:

let object = {
   "key1": "value1"
   "key2": "value2"
   "key3": "value3"
};

for (var key of Object.keys(p)) {
   console.log(key + " : " + object[key])
}

4

열거 할 수 없는 속성 을 반복하려는 경우 Object.getOwnPropertyNames(obj)지정된 객체에서 직접 찾은 모든 속성 (열거 가능 또는 불가능)의 배열을 반환하는 데 사용할 수 있습니다 .

var obj = Object.create({}, {
  // non-enumerable property
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});

obj.foo = 1; // enumerable property

Object.getOwnPropertyNames(obj).forEach(function (name) {
  document.write(name + ': ' + obj[name] + '<br/>');
});


2
환상적입니다.이 답변을 게시 해 주셔서 감사합니다. 나는 성찰하는 데 필요한 Error개체와 루프 또는에서 속성을 가져올 수 없습니다 _.forIn(err)호출. 를 사용하면 이전에는 얻을 수 없었던 Object.getOwnPropertyNames(err)모든 부분에 액세스 Error할 수있었습니다. 감사!
Pierce

4

누군가 조건이있는 arrayObject 를 반복 해야하는 경우 :

var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}];

for (var i=0; i< arrayObjects.length; i++) {
  console.log(arrayObjects[i]);
  
  for(key in arrayObjects[i]) {      
    
      if (key == "status" && arrayObjects[i][key] == "good") {
        
          console.log(key + "->" + arrayObjects[i][key]);
      }else{
          console.log("nothing found");
      }
   }
}


4

ES6을 고려하여 설탕 한 숟가락을 추가하고 객체의 속성을 반복하는 또 다른 접근법을 제공하고 싶습니다.

평범한 JS 객체는 상자 밖에서 반복 할 수 없으므로 for..of내용을 반복 하는 데 루프 를 사용할 수 없습니다 . 그러나 아무도 그것을 반복 가능하게 만들 수는 없습니다. .

우리가 book반대 하자 .

let book = {
  title: "Amazing book",
  author: "Me",
  pages: 3
}

book[Symbol.iterator] = function(){

  let properties = Object.keys(this); // returns an array with property names
  let counter = 0;
  let isDone = false;

  let next = () => {
    if(counter >= properties.length){
      isDone = true;
    }
    return { done: isDone, value: this[properties[counter++]] }
  }

  return { next };
}

우리가 만들었으므로 다음과 같이 사용할 수 있습니다.

for(let pValue of book){
  console.log(pValue);
}
------------------------
Amazing book
Me
3

또는 ES6 생성기 의 성능을 알고 있다면 코드를 훨씬 더 짧게 만들 수 있습니다.

book[Symbol.iterator] = function *(){

  let properties = Object.keys(this);
  for (let p of properties){
    yield this[p];
  }

}

물론, 레벨에서 Object반복 가능 하도록 모든 오브젝트에 이러한 동작을 적용 할 수 있습니다 prototype.

Object.prototype[Symbol.iterator] = function() {...}

또한 반복 가능한 프로토콜을 준수하는 객체를 새로운 ES2015 기능 스프레드 연산자 와 함께 사용할 수 있으므로 객체 속성 값을 배열로 읽을 수 있습니다.

let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]

또는 파괴 할당을 사용할 수 있습니다 .

let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3

위에서 제공 한 모든 코드로 JSFiddle 을 확인할 수 있습니다 .


코드가 키는 없지만 값을 생성한다는 것을 알았습니다. 키로 값을 반복 할 수 있습니까?
Pika

그래 넌 할수있어. "수율 [key, obj [key]];" 생성기 함수에서 다음 "for (let [key, value] of {}) {}"와 같이 사용
Artyom Pranovich

4

ES06부터 객체의 값을 배열로 얻을 수 있습니다.

let arrValues = Object.values( yourObject) ;

객체 값의 배열을 반환하고 프로토 타입에서 값을 추출하지 않습니다 !!

MDN DOCS Object.values ​​()

그리고 열쇠 ​​(이미 나 앞에서 여기에 대답했다)

let arrKeys   = Object.keys(yourObject);

대답은 키와 값을 모두 반환하는 솔루션을 묻습니다.
Sean Lindo

4

최신 ES 스크립트에서는 다음과 같이 할 수 있습니다.

let p = {foo: "bar"};
for (let [key, value] of Object.entries(p)) {
  console.log(key, value);
}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.