オブジェクトをメンバーとして持つプレーンなJavaScriptオブジェクトをループする方法は?


1600

オブジェクトである値を含む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"
    }
}

回答:


2114
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が同意しない(ため息)、obj [prop]を実行すると「オブジェクトはこのプロパティまたはメソッドをサポートしていません」と表示されます。これに対する解決策はまだ見つけていません。
user999717

2
@MildFuzzは、JSオブジェクトに数値キーが不要であると考える場合に実際に意味があります。オブジェクトを繰り返し処理することはできません。JS for inは従来のと非常によく似ていforeachます。
ジェイクウィルソン

4
for ... inは良い解決策ですが、for()ループでpromiseを使用する場合は注意してください。ループでvarを作成すると、promiseのthen関数でそれを使用できないためです。ループ内のvarは1回しか存在しないため、すべてのthen関数には、最後の値も同じです。その問題がある場合は、「Object.keys(obj).forEach」または以下の私の答えを試してください。
Biber 2016年

hasOwnPropertyは、ほとんどの場合、最新のブラウザー(IE9 +)では冗長です。
フィリュウス

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 in Object.keys
techiev2

6
この方法を使用する場合は、このエラーに注意してください:「TypeError:非オブジェクトで呼び出されたObject.keys」。for ... in ... hasOwnPropertyパターンは私が(オブジェクト、配列、ヌル、未定義、真、偽、数プリミティブ、オブジェクトを)伝えることができる限り、何で呼び出すことができます。
theazureshadow

2
IE7はこれをサポートしていないことに注意してください。
ポールD.ウェイト2013年

3
@ techiev2これらのテストは決して有効ではありませんでした。現在のパフォーマンス状態については、更新されたものを参照してください:jsperf.com/objdir/20
OrganicPanda

4
@ techiev2:Object.keys()遅くなるわけではなく、forEach()への繰り返しアクセス.lengthです!あなたは、古典的な使用している場合はfor代わりに-loopを、それはほとんど2倍の速さですfor..in+ hasOwnProperty()Firefoxの33で
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あなたの内側for- inループ。
Rory O'Kane

59
これは、オブジェクトにプロトタイプメソッドがある場合にのみ必要であることに注意してください。たとえば、ループしているオブジェクトが単なるJSONオブジェクトの場合、このチェックは必要ありません。
gitaarik

6
@rednaw Object.prototypeは変更できるため、安全のためにこのチェックを使用します。正気なスクリプトでそれを行うことはできませんが、非常識なブラウザ拡張機能によってページで実行されるスクリプトを制御することはできません。ブラウザ拡張機能はページで実行され(ほとんどのブラウザ上)、奇妙な問題を引き起こす可能性があります(たとえば、window.setTimeoutをnullに設定します!)。
robocat 2014

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
ES7でObject.entriesを使用する例では、矢印関数パラメーター[key、val]を次のように括弧で囲む必要があります: `Object.entries(myObj).forEach(([key、val])=> {/ *ステートメント* /}
puiu 2017年

6
Object.entriesとObject.keysがプロトタイプを反復しないという事実を追加すると便利です。これは、プロトタイプとfor inコンストラクトの大きな違いです。
steviejay 2017年

ありがとうございました
Blue Tram

95

Underscore.jsの_.each使用:

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

4
アンダースコアを使用しているTimに感謝します。迅速でクリーンなオプションを使用するのは間違いなく良いことです。
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ループよりも高速で実行されているため、どのような場合でもfor...of処理するときに使用することをお勧めしますObject.values(4番目と6番目のテスト)。

  • Firefoxでは、for...inループが非常に遅いため、反復中にキーをキャッシュしたい場合は、を使用することをお勧めしますObject.keys。さらに、Chromeは両方の構造を同じ速度で実行しています(最初と最後のテスト)。

ここでテストを確認できます:https : //jsperf.com/es7-and-misc-loops


2
ES7の例は、React Nativeで魅力的に機能します。
タイベイリー

うまく説明しました。ありがとう
Alok Ranjan

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

14
自分で関数が定義されているobj可能性があるため、からのhasOwnProperty関数を使用しないためObject.prototypeです。forこのようなループの前に試すことができobj.hasOwnProperty = function(){return false;}、どのプロパティに対しても反復されません。
Azder

4
答えには@Azder + 1、Object.prototype.hasOwnPropertyの良い点については+1 以前はアンダースコアライブラリのソースコードの中でそれを見ましたが、その理由はわかりません。
Samuel

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 2017


7

それを行うためのいくつかの方法...

1) 2つのレイヤーfor ... in loop ...

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で解決策を試しましたが、タイプエラーが発生します。あなたの答えは素晴らしく簡潔に見えます。それを機能させることができれば、それはおそらくより良い選択肢の1つでしょう。私はそれを理解しようとしましたが、あなたの解決策を理解していません。
TolMera 16

2
@TolMera修正済み。
2016

4

ECMAScript-2017は、1か月前に完成したばかりで、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を使用でき、コードを最適化するためにarrow関数を使用できます


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

このソリューションでは、オブジェクト全体とネストされたオブジェクトをディープトラバースできる置換を使用します。各レベルですべてのフィールドと値を取得します。各フィールドへのフルパスを取得する必要がある場合は、こちらをご覧ください


-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.