JavaScriptオブジェクトをループまたは列挙するにはどうすればよいですか?


2880

次のようなJavaScriptオブジェクトがあります。

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

今、私はすべてをループにしたいp要素(p1p2p3...)そして、そのキーと値を取得します。どうやってやるの?

必要に応じてJavaScriptオブジェクトを変更できます。私の最終的な目標は、いくつかのキーと値のペアをループ処理することであり、可能であればの使用を避けたいですeval


9
オブジェクトリテラルとJSONの混同を避けるために、JSONをJavaScript(オブジェクト)に変更しました。
Felix Kling 2012年

回答:


4367

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()代替のfor-of:

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でネイティブにサポートされていません。古いブラウザでは、ポリフィルの使用を検討してください。

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の必要性を説明できますか?プロトタイプとはどういう意味ですか?
カマシ

331
JavaScriptでは、すべてのオブジェクトにメタ情報を持つ組み込みのキーと値のペアがたくさんあります。オブジェクトのすべてのキーと値のペアをループすると、それらもループします。hasOwnPropery()はこれらを除外します。
danieltalsky 2012年

57
実際、For ... inは非推奨はありません。 それぞれについて、...です。しかし、私は考古学者という言葉が本当に好きです...私はそれを使い始める必要があります。
Ben Y

17
JavaScriptの各オブジェクト(実際にはキーと値のペア)には、__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、分解、およびを組み合わせることができますObject.entries

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

両方とも、ループと同じ順序でプロパティObject.keys()Object.entries()反復しfor...inますが、プロトタイプチェーンは無視します。オブジェクト自体の列挙可能なプロパティのみが反復されます。


21
標準が提供しなかったのはなぜObject.forEach(obj, function (value, key) {...})ですか?:(確かにobj.forEach(function...)短くし、補体だろうArray.prototype.forEachが、それは、オブジェクトが独自の定義持つ危険がforEach財産を私は考えます。Object.keysオブジェクトのキー変更するコールバックを保護します。
デビッド・ハークネスを

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

7
@DavidHarkness ES2017にはObject.entriesがあります。そこでは次のことができます:Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([key、value]は配列の構造化であり、両方の項目に直接アクセスします。さらに、パラメーターを追加の括弧で
囲む

indexjsonでキーを取得するにはどうすればよいですか?または、必要に応じて別のカウンターを使用する必要がありますか?
サラバナバラギラマチャンドラン2017

3
for...ofES2016ではなく、ES6標準です。
Rax Weber 2017

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
メインロジックを2つではなく1つのネストされたループにできるため、これはlevikのソリューションよりも優れています。コードを読みやすくします。続けてブラケットを緩めますが、彼らは不必要です。
SystemicPlural

52
{ }個人的には削除しません。これらがないと、何が含まれていifif、何がそうでないかが少し不明確になるためです。しかし、それは単なる意見の問題だと思います:)
pimvdb '05 / 08/05

34
はい、{ }後で何かをifスコープに追加する必要がある場合に混乱を避けるために、主に保持することを好みます。
Andreas Grech

8
以前のコメントを読んで、「ifスコープ」と言ったので、正しい用語を使用していないことに気付きました。ただし、JavaScriptには関数スコープしかありません。だから私が実際に意味したのは「if block」だった。
Andreas Grech

1
eomeroff、あなたが本当にそれを心配しているなら、あなたはいつも次のようなことをすることができます: Object.prototype.hasOwnProperty.call(p, prop) しかし、これもObject.prototypeへの操作から保護することはできません...
jordancpaul

252

オブジェクトをループする別の方法について言及しなければ、質問は完全ではありません。

現在、多くの有名なJavaScriptライブラリは、コレクション、つまり配列オブジェクト配列のようなオブジェクトを反復処理するための独自のメソッドを提供しています。これらのメソッドは使いやすく、すべてのブラウザと完全に互換性があります。

  1. あなたがで作業する場合jQueryを、あなたは使用することができますjQuery.each()方法を。オブジェクトと配列の両方をシームレスに反復するために使用できます。

    $.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は、オブジェクトプロパティを反復するためのいくつかのメソッドを提供します。Basic _.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の互換表で確認できるブラウザーサポート

古いブラウザの場合、シンプル完全なポリフィルがあります

UPD:

この質問で最も人気のあるすべてのケースのパフォーマンス比較perfjs.info

オブジェクトリテラルの反復


確かに、私はこのメソッドを投稿したかっただけです。しかし、あなたは私にそれを打ち負かしました:(
ジェイミーハットバー

50

序文:

  • オブジェクトのプロパティは、所有することも(プロパティはオブジェクト自体にある)、継承することもできます(オブジェクト自体ではなく、プロトタイプの1つにあります)。
  • オブジェクトプロパティは、列挙可能または非列挙可能です。列挙できないプロパティは、多くのプロパティの列挙/配列から除外されています。
  • プロパティ名は文字列またはシンボルです。名前がシンボルであるプロパティは、多くのプロパティ列挙/配列から除外されています。

ここ2018年、オブジェクトのプロパティをループするためのオプションは次のとおりです(一部の例はリストに従います)。

  1. for-in[ MDNspec ] — 名前が文字列である継承されたプロパティを含む、オブジェクトの列挙可能なプロパティの名前をループするループ構造
  2. Object.keys[ MDNスペック ] -オブジェクトの名の配列提供機能自体列挙名文字列である性質を。
  3. Object.values[ MDNスペック ] -の配列提供関数オブジェクトのの自身の列挙プロパティを。
  4. Object.entries[ MDNスペック ] -名前の配列提供機能、オブジェクトの値自身列挙プロパティを(アレイ内の各エントリは、ある[name, value]配列)。
  5. Object.getOwnPropertyNames[ MDNspec ] — 名前が文字列であるオブジェクト自体のプロパティ(列挙できないものも含む)の名前の配列を提供する関数。
  6. Object.getOwnPropertySymbols[ MDNspec ] — 名前がSymbols であるオブジェクト自身のプロパティ(列挙できないものも含む)の名前の配列を提供する関数。
  7. Reflect.ownKeys[ MDNspec ] — 名前が文字列かシンボルかに関係なく、オブジェクト自体のプロパティ(列挙できないものも含む)の名前の配列を提供する関数。
  8. あなたがしたい場合は、すべての非可算継承されたものも含めて、オブジェクトのプロパティ、のを、あなたがループして使用する必要があるObject.getPrototypeOf[ MDNスペック ]及び使用をObject.getOwnPropertyNamesObject.getOwnPropertySymbolsまたはReflect.ownKeys(この答えの下部にある例)各プロトタイプチェーン内のオブジェクトに。

除いて、それらのすべてでfor-in、あなたは(アレイ上の構造物をループのいくつかの種類を使用したいforfor-offorEach、など)。

例:

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
私は最初、この回答が最初に来ることに気づくまで、上記のコメントに基づいてこれに反対票を投じたため、「繰り返されません」。おそらく不完全ですが、多くの場合問題なく動作します。
ビリーノア2018年

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) 'を実行できるようにすることだと思いました。それは、ほとんど追加の価値を提供しない追加のコードのように見えます。
ディーンラドクリフ

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

注:配列に対してこれを行うことができますが、lengthおよびその他のプロパティについても繰り返します。


4
そのようなforループを使用する場合key、インデックス値を取得するだけなので、0、1、2などを警告するだけです。p[key]にアクセスする必要があります。
ブライアン

1
これは、JavaScriptでの配列反復の最も遅い方法です。これをコンピュータで確認できます-JavaScriptで配列を反復処理する最良の方法
Pencroff

5
@ペンクロフ:問題は、配列をループすることではないということです...;)
Sk8erPeter

これは私がstackoverflowで理解していないものです。リチャードは正しい答えを出しました、そして彼はその答えを出した最初の人でした、しかし彼は+1を得ませんでしたか?@ブライアンvar p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }はアラートで「p1」と「p2」をポップしているので、それについて何が間違っていますか?
セバスチャン

5
主な違いは品質だと思います。他の答えは、方法だけでなく、警告(たとえば、プロトタイプ)とそれらの警告への対処方法も伝えます。私見、それらの他の答え私のものより優れています:)。
Richard Levasseur 2014

20

ここですべての回答を確認した後、jsonオブジェクトはクリーンであるため、自分の使用にはhasOwnPropertyは必要ありません。追加のJavaScript処理を追加しても意味がありません。これが私が使っているすべてです:

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

18
JSONオブジェクトがクリーンであるかどうかは関係ありません。それ以外のときに、いくつかのコードがプロパティをに設定するObject.prototypeと、それはによって列挙されfor..inます。それを行うライブラリを使用していないことが確実な場合は、を呼び出す必要はありませんhasOwnProperty
G-Wiz 2012年

4
次のもので作成された場合、完全にクリーンになりますObject.create(null)
Juan Mendes

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 }生産しますTypeError: number is not a function。を使用forEachして同様のArray機能を照合すると、リスクが多少軽減される場合があります。
David Harkness 2014年

18

これは、これらの答えの人々が、両方に触れている面白いObject.keys()for...ofが、それらを組み合わせることはありません。

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

あなたはできるだけでなく、それはイテレータではない、とするのでまたはINGの醜い/非効率的です。 これは少し面倒なので、ほとんどの人が(チェックの有無にかかわらず)遠慮しているので、上記の私の回答以外に、私はここで...for...ofObjectfor...index.forEach()Object.keys()
for...in.hasOwnProperty()


通常のオブジェクトの関連付けを繰り返すことができます!Mapfor...ofChromeとFFで動作するファンシーな
デモを直接使用してsのように動作する(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:'!'});

シムを作成したくない、またはprototype一般的に混乱したくない場合は、代わりにwindowで関数を作成して、そのようなものを呼び出してください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
ケース のポイント。人々が下にスクロールしてそれが役立つと考える限り、それだけが重要です。通常、私はオンラインで目にするものを好きではなく、何かをしようとしているのです。結局それを理解し、それから共有に戻ります。それは良いドコです、私が完全に忘れていたものをググる前に、私は実際に自分の答えに出くわしました!
ハッシュブラウン

@HelpMeStackOverflowMyOnlyHope個人的には、自分で定義していないオブジェクトのプロトタイプを変更したくありません。
Janus Troelsen 2016

@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;
ハッシュブラウン2016

この手法はプレーンオブジェクトでは機能しませんが、それでも役立ちます。
noɥʇʎԀʎzɐɹƆ

それはプレーンオブジェクトに対して機能します。それは文字通り全体のポイントです(そしてordinaryObject、マジックがそれらの型に対してまだ機能することを強調するための変数名と同様に)。デモを確認しましたか。@noɥʇʎԀʎzɐɹƆさん、何がうまくいかないのですか?(PSあなたのSEのプロフィール画像はボスです)
ハッシュブラウン

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ミリ秒かかりました。

PS。Chromeでは、さらに大きな違い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);
});


{}表記を手放したくない場合でも、s 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]);
});


あなたは私の時間を節約しました、ありがとう
Swap-IOS-Android

知って幸せ:)
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(新しい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年には、JavaScriptでループするための実際の確実な方法は、多くの一般的なライブラリ(jQuery、Underscoreなど)が再実装することを決定したもの以外にありません。

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

私はchromeを使用していUncaught TypeError: Object.entries is not a functionます。まだChromeに実装されていませんか?
abalter

@abalterです。私の編集とJsfiddleのコメントで説明されているように、Chromeバージョン51があり、フラグが有効になっていることを確認してください。あなたは、ここで詳細を確認することができますdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
ニコラスBouvrette

申し訳ありませんが、フラグについては見逃しました。まだ完全に実装されている機能ではないようです。
abalter

5

ES6には、以前の内部メソッドを公開するためのよく知られたシンボルがあります。これを使用して、このオブジェクトのイテレータの動作を定義できます。

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

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

これは、es6ループでfor ...を使用した場合と同じ結果になります。

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

しかし、es6を使用して現在持っている機能を知ることは重要です!


1
カスタムオブジェクトイテレータは、Object.keys()メモリによって生成され、メモリに割り当てられた配列の組み込み配列イテレータを呼び出します。
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]); } } }
MarekBernád18年

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

誰かがarrayObjectsを条件付きでループする必要がある場合:

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を考慮して、独自の砂糖のスプーンを追加し、オブジェクトのプロパティを反復処理するもう1つのアプローチを提供します。

単純な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];
  }

}

もちろん、このような動作をすべてのオブジェクトに適用してObjectprototypeレベルで反復可能にすることができます。

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をチェックアウトできます。


コードは値を生成しますが、キーはありません。キーで値を繰り返すことは可能ですか?
ピカ2016

はい、できます。「yield [key、obj [key]];」を返すだけです。ジェネレーター関数から、次のように使用します "for(let [key、value] of {}){}"
Artyom Pranovich

4

ES06以降では、オブジェクトの値を配列として取得できます

let arrValues = Object.values( yourObject) ;

オブジェクト値の配列を返し、Prototypeから値を抽出しません!!

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.