객체를 멤버로 사용하여 일반 JavaScript 객체를 반복하는 방법은 무엇입니까?


1599

객체 값을 포함하여 JavaScript 객체의 모든 멤버를 반복하는 방법

예를 들어 이것을 어떻게 반복 할 수 있습니까 (각각 "your_name"및 "your_message"에 액세스)?

var validation_messages = {
    "key_1": {
        "your_name": "jimmy",
        "your_msg": "hello world"
    },
    "key_2": {
        "your_name": "billy",
        "your_msg": "foo equals bar"
    }
}

답변:


2113
for (var key in validation_messages) {
    // skip loop if the property is from prototype
    if (!validation_messages.hasOwnProperty(key)) continue;

    var obj = validation_messages[key];
    for (var prop in obj) {
        // skip loop if the property is from prototype
        if (!obj.hasOwnProperty(prop)) continue;

        // your code
        alert(prop + " = " + obj[prop]);
    }
}

13
Internet Explorer가 동의하지 않습니다 ( sigh ). obj [prop]를 수행 할 때 "개체가이 속성 또는 메서드를 지원하지 않습니다"라고 말합니다. 아직 이것에 대한 해결책을 찾지 못했습니다.
user999717

2
@MildFuzz 실제로 JS 객체에 숫자 키가 필요하지 않다고 생각하면 의미가 있습니다. 객체를 반복 할 수는 없습니다. JS for in는 전통적인 것과 매우 유사합니다 foreach.
Jake Wilson

4
for ... in은 좋은 해결책이지만 for () 루프에서 promise를 사용하면 루프에서 var를 만들면 promise의 then-function에서 사용할 수 없으므로주의하십시오. 루프의 var는 한 번만 존재하므로 모든 함수에서 마지막 값까지도 동일합니다. 그 문제가 발생하면 "Object.keys (obj) .forEach"또는 아래의 답변을 시도하십시오.
Biber

775

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

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

//
//	Visit non-inherited enumerable keys
//
Object.keys(obj).forEach(function(key) {

  console.log(key, obj[key]);

});


34
코드는 간결하지만 +1이지만 놀랍게도 효율적이지 않습니다. JSPerf-for vs. Object.keys
techiev2

6
"TypeError : Object.keys on non-object"접근 방식을 사용하여이 오류를주의하십시오. for ... in ... hasOwnProperty패턴은 내가 (객체, 배열, 널 (null), 정의되지 않은, 참, 거짓, 수 원시, 객체)를 말할 수있는 지금까지, 아무것도 호출 할 수 있습니다.
theazureshadow

2
IE7은이를 지원하지 않습니다.
Paul D. Waite

3
@ techiev2 해당 테스트는 유효하지 않습니다. jsperf.com/objdir/20
OrganicPanda

4
@ techiev2 : Object.keys()느리게 만드는 것이 아니라 오히려 forEach()반복되는 액세스입니다 .length! 클래식 for루프를 대신 사용하면 Firefox 33에서 for..in+ 보다 거의 두 배 빠릅니다 hasOwnProperty().
CodeManX

384

이것에 대한 문제

for (var key in validation_messages) {
   var obj = validation_messages[key];
   for (var prop in obj) {
      alert(prop + " = " + obj[prop]);
   }
}

또한 기본 객체의 프로토 타입을 반복합니다.

이것으로 당신은 그것을 피할 것입니다 :

for (var key in validation_messages) {
   if (validation_messages.hasOwnProperty(key)) {
      var obj = validation_messages[key];
      for (var prop in obj) {
         if (obj.hasOwnProperty(prop)) {
            alert(prop + " = " + obj[prop]);
         }
      }
   }
}

46
요컨대 - 루프 hasOwnProperty내부를 확인하십시오 . forin
Rory O'Kane 5

59
이것은 오브젝트에 프로토 타입 메소드가있는 경우에만 필요합니다. 예를 들어, 반복하려는 객체가 JSON 객체 인 경우이 검사가 필요하지 않습니다.
gitaarik

6
@rednaw 안전을 위해 Object.prototype을 수정할 수 있기 때문에 해당 검사를 사용합니다. 제정신의 스크립트는 그렇게하지 않지만 당신은 제정신 브라우저 확장 프로그램에 의해 페이지에서 실행될 스크립트를 제어 할 수 없습니다. 브라우저 확장 프로그램은 대부분의 브라우저에서 페이지에서 실행되며 이상한 문제를 일으킬 수 있습니다 (예 : window.setTimeout을 null로 설정)!
robocat

1
정말 감사합니다
Blue Tram

328

ES6 / 2015 에서는 다음 과 같은 객체를 반복 할 수 있습니다. ( 화살표 기능 사용 )

Object.keys(myObj).forEach(key => {
  console.log(key);        // the name of the current key.
  console.log(myObj[key]); // the value of the current key.
});

jsbin

ES7 / 2016 에서는 다음 과 같이 Object.entries대신 Object.keys객체를 사용하고 객체를 반복 할 수 있습니다 .

Object.entries(myObj).forEach(([key, val]) => {
  console.log(key); // the name of the current key.
  console.log(val); // the value of the current key.
});

위의 내용은 단일 라이너 로도 작동합니다 .

Object.entries(myObj).forEach(([key, val]) => console.log(key, val));

jsbin

중첩 된 객체를 반복하려는 경우 재귀 함수 (ES6)를 사용할 수 있습니다 .

const loopNestedObj = obj => {
  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === "object") loopNestedObj(obj[key]); // recurse.
    else console.log(key, obj[key]); // or do something with key and val.
  });
};

jsbin

위의 기능과 동일하지만 대신 ES7을 Object.entries() 사용하십시오 Object.keys().

const loopNestedObj = obj => {
  Object.entries(obj).forEach(([key, val]) => {
    if (val && typeof val === "object") loopNestedObj(val); // recurse.
    else console.log(key, val); // or do something with key and val.
  });
};

여기에서 중첩 된 객체 변경 값을 반복 Object.entries()하고 Object.fromEntries()( ES10 / 2019 ) 와 결합 하여 한 번에 새 객체를 반환합니다 .

const loopNestedObj = obj =>
  Object.fromEntries(
    Object.entries(obj).map(([key, val]) => {
      if (val && typeof val === "object") [key, loopNestedObj(val)]; // recurse
      else [key, updateMyVal(val)]; // or do something with key and val.
    })
  );

2
Object.entries 예제를 사용하는 ES7의 경우 화살표 함수 매개 변수 [key, val]을 괄호로 묶어야합니다.`Object.entries (myObj) .forEach (([key, val]) => {/ * statement * /}
puiu

6
Object.entries와 Object.keys가 프로토 타입을 반복하지 않는다는 사실을 추가하는 것이 유용하다고 생각합니다.
steviejay

정말 감사합니다
Blue Tram

95

Underscore.js_.each 사용 :

_.each(validation_messages, function(value, key){
    _.each(value, function(value, key){
        console.log(value);
    });
});

4
감사합니다. 팀은 밑줄을 사용하여 빠르고 깔끔한 옵션을 사용하는 것이 좋습니다.
Coder

56

재귀를 사용하면 모든 깊이의 객체 속성을 반환 할 수 있습니다

function lookdeep(object){
    var collection= [], index= 0, next, item;
    for(item in object){
        if(object.hasOwnProperty(item)){
            next= object[item];
            if(typeof next== 'object' && next!= null){
                collection[index++]= item +
                ':{ '+ lookdeep(next).join(', ')+'}';
            }
            else collection[index++]= [item+':'+String(next)];
        }
    }
    return collection;
}

//example

var O={
    a:1, b:2, c:{
        c1:3, c2:4, c3:{
            t:true, f:false
        }
    },
    d:11
};
var lookdeepSample= 'O={'+ lookdeep(O).join(',\n')+'}';


/*  returned value: (String)
O={
    a:1, 
    b:2, 
    c:{
        c1:3, c2:4, c3:{
            t:true, f:false
        }
    },
    d:11
}

*/

2
DOM 노드에서 이것을 호출하는 것과 같은 루프에주의하십시오.
theazureshadow

45

이 답변은이 게시물에서 일부 성능 피드백 과 함께 제공된 솔루션의 집합입니다 . 나는 2 개의 유스 케이스가 있다고 생각하고 OP는 루프 프로세스 중에 키를 액세스하기 위해 키에 액세스 해야하는지 언급하지 않았다.

I. 키에 액세스해야합니다.

ofObject.keys접근

let k;
for (k of Object.keys(obj)) {

    /*        k : key
     *   obj[k] : value
     */
}

in접근법

let k;
for (k in obj) {

    /*        k : key
     *   obj[k] : value
     */
}

프로토 타입의 속성을 인쇄 할 수 있으므로주의해서 사용하십시오. obj

✔ ES7 접근

for (const [key, value] of Object.entries(obj)) {

}

그러나 JavaScript는이 프로 시저를 빌드하기 위해 내부적으로 많은 변수를 초기화하기 때문에 ES7 방법을 권장하지 않습니다 (증거에 대한 피드백 참조). 최적화가 필요한 거대한 앱을 개발하지 않는 한 괜찮습니다.하지만 최적화가 우선 순위라면 생각해야합니다.

II. 각 값에 액세스하면됩니다.

ofObject.values접근

let v;
for (v of Object.values(obj)) {

}

테스트에 대한 추가 피드백 :

  • 캐싱 Object.keys또는 Object.values성능은 무시할 수 있습니다

예를 들어

const keys = Object.keys(obj);
let i;
for (i of keys) {
  //
}
// same as
for (i of Object.keys(obj)) {
  //
}
  • 예를 들어 Firefox에서 캐시 된 변수와 함께 Object.values기본 for루프를 사용하는 것이 for...of루프를 사용하는 것보다 약간 더 빠릅니다 . 그러나 차이점은 그다지 중요하지 않으며 Chrome이 for...of기본 for루프 보다 빠르게 실행 되므로 모든 경우 (4 및 6 테스트)를 for...of처리 할 때 사용하는 것이 좋습니다 Object.values.

  • Firefox에서는 for...in루프가 실제로 느리므로 반복하는 동안 키를 캐시하려면 사용하는 것이 좋습니다 Object.keys. 또한 Chrome은 두 가지 구조를 동일한 속도로 실행합니다 (첫 번째 및 마지막 테스트).

여기에서 테스트를 확인할 수 있습니다 : https://jsperf.com/es7-and-misc-loops


2
ES7 예제는 React Native의 매력처럼 작동합니다!
Ty Bailey

잘 설명했다. 감사합니다
알록 란잔

30

나는 그것이 늦었다는 것을 알고 있지만 AgileJon의 대답의 최적화되고 개선 된 버전을 작성하는 데 2 ​​분이 걸렸습니다.

var key, obj, prop, owns = Object.prototype.hasOwnProperty;

for (key in validation_messages ) {

    if (owns.call(validation_messages, key)) {

        obj = validation_messages[key];

        for (prop in obj ) {

            // using obj.hasOwnProperty might cause you headache if there is
            // obj.hasOwnProperty = function(){return false;}
            // but owns will always work 
            if (owns.call(obj, prop)) {
                console.log(prop, "=", obj[prop]);
            }

        }

    }

}

1
왜 저장되어 hasOwnProperty에서 owns다음 호출 owns.call(obj, prop)호출 단지 대신 obj.hasOwnProperty(prop)으로 이 대답은 무엇입니까?
Rory O'Kane 5

14
때문에 obj있을 수 있습니다 hasOwnProperty함수가 정의 자체는 그래서에서 하나를 사용하지 않습니다 Object.prototype. for이런 식으로 루프를 시도해 볼 수 있으며 obj.hasOwnProperty = function(){return false;}속성을 반복하지 않습니다.
Azder

4
@Azder는 대답에 +1이고 Object.prototype.hasOwnProperty에 대해 좋은 점이 있다면 +1입니다. 이전에 밑줄 라이브러리의 소스 코드 내부에서이를 보았지만 이유를 모르겠습니다.
사무엘

29
for(var k in validation_messages) {
    var o = validation_messages[k];
    do_something_with(o.your_name);
    do_something_else_with(o.your_msg);
}

14

p는 값이다

for (var key in p) {
  alert(key + ' => ' + p[key]);
}

또는

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

9

ES7에서는 다음을 수행 할 수 있습니다.

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

몇 가지 테스트를 했는데이 방법은 많은 양의 데이터를 처리 할 때 실제로 느립니다.
vdegenne

8
for(var key in validation_messages){
    for(var subkey in validation_messages[key]){
        //code here
        //subkey being value, key being 'yourname' / 'yourmsg'
    }
}

7

그렇게하는 몇 가지 방법 ...

1) 루프 용 2 개의 레이어 ...

for (let key in validation_messages) {
   const vmKeys = validation_messages[key];
   for (let vmKey in vmKeys) {
      console.log(vmKey + vmKeys[vmKey]);
   }
}

2) 사용Object.key

Object.keys(validation_messages).forEach(key => {
   const vmKeys = validation_messages[key];
   Object.keys(vmKeys).forEach(key => {
    console.log(vmKeys + vmKeys[key]);
   });
});

3) 재귀 기능

const recursiveObj = obj => {
  for(let key in obj){
    if(!obj.hasOwnProperty(key)) continue;

    if(typeof obj[key] !== 'object'){
      console.log(key + obj[key]);
    } else {
      recursiveObj(obj[key]);
    }
  }
}

그리고 다음과 같이 호출하십시오.

recursiveObj(validation_messages);

5

다음은 AgileJon 솔루션의 개선 된 재귀 버전 ( 데모 )입니다.

function loopThrough(obj){
  for(var key in obj){
    // skip loop if the property is from prototype
    if(!obj.hasOwnProperty(key)) continue;

    if(typeof obj[key] !== 'object'){
      //your code
      console.log(key+" = "+obj[key]);
    } else {
      loopThrough(obj[key]);
    }
  }
}
loopThrough(validation_messages);

이 솔루션은 모든 종류의 다양한 깊이에서 작동합니다.


5

다른 옵션 :

var testObj = {test: true, test1: false};
for(let x of Object.keys(testObj)){
    console.log(x);
}

Chrome 55.0에서 솔루션을 시도했지만 유형 오류가 발생합니다. 대답은 멋지고 간결 해 보입니다. 작동하게하면 더 좋은 옵션 중 하나 일 것입니다. 나는 그것을 이해하려고 노력했지만 귀하의 솔루션을 이해하지 못합니다.
TolMera

2
@TolMera 수정되었습니다.
친구

4

한 달 전에 마무리 된 ECMAScript-2017에는 Object.values ​​()가 도입되었습니다. 이제 당신은 이것을 할 수 있습니다 :

let v;
for (v of Object.values(validation_messages))
   console.log(v.your_name);   // jimmy billy

3

jQuery가 이것을 잘 정렬한다는 것을 지적 할 가치가 있다고 생각합니다. $.each() .

참조 : https://api.jquery.com/each/

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

$('.foo').each(function() {
    console.log($(this));
});

$(this)객체 내부의 단일 항목입니다. 스왑 $('.foo')변수에 당신은 jQuery의 셀렉터 엔진을 사용하지 않으려면.


3

var obj={
name:"SanD",
age:"27"
}
Object.keys(obj).forEach((key)=>console.log(key,obj[key]));

JavaScript 객체를 반복하기 위해 forEach를 사용할 수 있고 코드를 최적화하기 위해 화살표 함수를 사용할 수 있습니다


2

위의 게시물을 통해 내가 한 일을 할 수 없었습니다.

다른 답글을 가지고 놀고 난 후에 이것을 만들었습니다. 해 키지 만 작동합니다!

이 객체의 경우 :

var myObj = {
    pageURL    : "BLAH",
    emailBox   : {model:"emailAddress", selector:"#emailAddress"},
    passwordBox: {model:"password"    , selector:"#password"}
};

...이 코드 :

// Get every value in the object into a separate array item ...
function buildArray(p_MainObj, p_Name) {
    var variableList = [];
    var thisVar = "";
    var thisYes = false;
    for (var key in p_MainObj) {
       thisVar = p_Name + "." + key;
       thisYes = false;
       if (p_MainObj.hasOwnProperty(key)) {
          var obj = p_MainObj[key];
          for (var prop in obj) {
            var myregex = /^[0-9]*$/;
            if (myregex.exec(prop) != prop) {
                thisYes = true;
                variableList.push({item:thisVar + "." + prop,value:obj[prop]});
            }
          }
          if ( ! thisYes )
            variableList.push({item:thisVar,value:obj});
       }
    }
    return variableList;
}

// Get the object items into a simple array ...
var objectItems = buildArray(myObj, "myObj");

// Now use them / test them etc... as you need to!
for (var x=0; x < objectItems.length; ++x) {
    console.log(objectItems[x].item + " = " + objectItems[x].value);
}

... 콘솔에서 이것을 생성합니다.

myObj.pageURL = BLAH
myObj.emailBox.model = emailAddress
myObj.emailBox.selector = #emailAddress
myObj.passwordBox.model = password
myObj.passwordBox.selector = #password

0

나를 위해 일하는 해결책은 다음과 같습니다.

_private.convertParams=function(params){
    var params= [];
    Object.keys(values).forEach(function(key) {
        params.push({"id":key,"option":"Igual","value":params[key].id})
    });
    return params;
}

0

이국적인 하나-깊은 트래버스

JSON.stringify(validation_messages,(field,value)=>{
  if(!field) return value;

  // ... your code

  return value;
})

이 솔루션에서는 전체 객체와 중첩 된 객체를 깊게 통과 할 수있는 replacer 를 사용합니다. 각 수준에서 모든 필드와 값을 가져옵니다. 각 필드 에 대한 전체 경로 를 얻으려면 여기를보십시오


-6

필자의 경우 (이전 기준) 여러 수준이 가능합니다.

var myObj = {
    rrr: undefined,
    pageURL    : "BLAH",
    emailBox   : {model:"emailAddress", selector:"#emailAddress"},
    passwordBox: {model:"password"    , selector:"#password"},
    proba: {odin:{dva:"rr",trr:"tyuuu"}, od:{ff:5,ppa:{ooo:{lll:'lll'}},tyt:'12345'}}
};


function lookdeep(obj,p_Name,gg){
    var A=[], tem, wrem=[], dd=gg?wrem:A;
    for(var p in obj){
        var y1=gg?'':p_Name, y1=y1 + '.' + p;
        if(obj.hasOwnProperty(p)){
           var tem=obj[p];
           if(tem && typeof tem=='object'){
               a1=arguments.callee(tem,p_Name,true);
               if(a1 && typeof a1=='object'){for(i in a1){dd.push(y1 + a1[i])};}
            }
            else{
               dd.push(y1 + ':' + String(tem));
            }
        }
    };
    return dd
};


var s=lookdeep(myObj,'myObj',false);
for (var x=0; x < s.length; ++x) {
console.log(s[x]+'\n');}

결과:

["myObj.rrr:undefined",
"myObj.pageURL:BLAH",
"myObj.emailBox.model:emailAddress",
"myObj.emailBox.selector:#emailAddress",
"myObj.passwordBox.model:password",
"myObj.passwordBox.selector:#password",
"myObj.proba.odin.dva:rr",
"myObj.proba.odin.trr:tyuuu",
"myObj.proba.od.ff:5",
"myObj.proba.od.ppa.ooo.lll:lll",
"myObj.proba.od.tyt:12345"]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.