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




typescript object loop (20)

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

私は次のようなJavaScriptオブジェクトを持っています:

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

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

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


ECMAScript 5では、 Object.keys()Array.prototype.forEach()組み合わせることができます。

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

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

ES6は〜のfor...of追加for...of

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

ES2017では、元のオブジェクトの各値を検索する必要がないObject.entries()が追加されています。

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

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

編集:ES2016→ES6


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ページを参照してください。


Object.keys()メソッドは、指定されたオブジェクト自身の列挙可能なプロパティの配列を返します。 詳細はObject.keys()

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

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


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
}

プロトタイプチェーンプロパティをスキップする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

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

let arrValues = Object.values( yourObject) ;

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

MDN DOCS Object.values()

キーのために(allreadyは私の前にここで答える)

let arrKeys   = Object.keys(yourObject);

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

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

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

これは、es6ループで...を使用するのと同じ結果をもたらします。

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

しかし、es6を使用している機能を知ることが重要です!


あなたはそれのようにそれを繰り返すことができます:

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

keyはプロパティの値をとらないことに注意してください。これは単なるインデックス値です。


これらの答えの中の興味深いのはObject.keys()for...of両方に触れていfor...of 、それらを組み合わせたことはありません:

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

iteratorではなく、 for...indexまたは.forEach()するのは、醜い/非効率的for...ofあるため、 Objectためだけfor...of使うことはできません。
私は、ほとんどの人が控えていることを嬉しく思っfor...infor...in .hasOwnProperty()をチェックしてもしなくても)ちょっと面倒なので、上記の私の答え以外に、私はここにいます...

普通のオブジェクトの関連付けを反復させることができます! Mapのように振る舞いfor...of
Chromeと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:'!'});

シムしたくない人や、一般的にprototypegetObjIterator() 、代わりに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))

それがうまくいかない理由はありません。

未来へようこそ。


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

今日、よく知られている多くの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は、オブジェクトのプロパティを反復処理するためのいくつかのメソッドを提供します。 基本的な_.forEach() (またはエイリアス_.each() )は、オブジェクトと配列の両方をループするのに便利ですが、 lengthプロパティを持つ(!)オブジェクトは配列のように扱われます。 _.forIn()_.forOwn()メソッド(これらも最初にvalue引数がありvalue ):

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

    _.forIn()は、オブジェクトの独自のプロパティまたは継承された enumerableプロパティを繰り返し処理しますが、 _.forOwn()はオブジェクトの独自のプロパティに対してのみ繰り返します(基本的にhasOwnProperty関数をチェックします)。 単純なオブジェクトとオブジェクトリテラルの場合、これらのメソッドのいずれかが正常に動作します。

一般に、記述されたすべてのメソッドは、指定されたオブジェクトと同じ動作をします。 ネイティブfor..inループの使用に加えて、通常はjQuery.each()などの抽象化より高速ですが、これらのメソッドはかなり使いやすく、コーディングが少なく、エラー処理が優れています。


オブジェクトを反復処理する別の方法があります。

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


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


単純な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 ... in "を気に入らない人のために - 方法:

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と競合したくない場合は、固有の名前で名前を付けることができます。


序文:

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

ここで2018年に、オブジェクトのプロパティをループするオプションは次のとおりです。

  1. for-in [ MDNspec ] - オブジェクトの列挙可能なプロパティの名前をループするループ構造。継承されたものを含み、名前は文字列です
  2. Object.keys [ MDNspec ] - 名前が文字列である、オブジェクト自身の 列挙可能なプロパティの名前の配列を提供する関数。
  3. Object.values [ MDNspec ] - オブジェクト自身の 列挙可能なプロパティのの配列を提供する関数。
  4. Object.entries [ MDNspec ] - オブジェクト自身の 列挙可能なプロパティの名前値の配列を提供する関数。
  5. Object.getOwnPropertyNames [ MDNspec ] - 名前が文字列であるオブジェクト自身のプロパティの名前の配列(列挙できないものも含む)の配列を提供する関数です。
  6. Object.getOwnPropertySymbols [ MDNspec ] - 名前がシンボルであるオブジェクト自身のプロパティ(列挙できないものも含む)の名前の配列を提供する関数です。
  7. Reflect.ownKeys [ MDNspec ] - オブジェクト自体のプロパティの名前の配列(列挙できないものも含む)を提供する関数。名前が文字列かシンボルかにかかわらず。
  8. 継承できない列挙型を含むオブジェクトのすべてのプロパティを必要とする場合は、ループとObject.getPrototypeOf [ MDNspec ]を使用し、 Object.getOwnPropertyNamesObject.getOwnPropertySymbols 、またはReflect.ownKeysをそれぞれのオブジェクトに使用する必要があります。プロトタイプチェーン(この回答の一番下の例)。

これらをすべてfor-in以外for-in使うと、配列のforループ、 forEachforEachなどのループ構造を使用します。

例:

for-in

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name in o) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.keys for-ofループを使用しますが、任意のループ構造を使用できます)

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.keys(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.values

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const value of Object.values(o)) {
    console.log(`${value}`);
}

Object.entries

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const [name, value] of Object.entries(o)) {
    console.log(`${name} = ${value}`);
}

Object.getOwnPropertyNames

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.getOwnPropertyNames(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.getOwnPropertySymbols

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.getOwnPropertySymbols(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}

Reflect.ownKeys

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Reflect.ownKeys(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}

継承された非列挙型を含むすべてのプロパティ

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (let depth = 0, current = o; current; ++depth, current = Object.getPrototypeOf(current)) {
    for (const name of Reflect.ownKeys(current)) {
        const value = o[name];
        console.log(`[${depth}] ${String(name)} = ${String(value)}`);
    }
}
.as-console-wrapper {
  max-height: 100% !important;
}


私のjsonオブジェクトがきれいなので、ここですべての答えを調べた後、hasOwnPropertyは自分自身の使用に必須ではありません。 追加のJavaScript処理を追加する意味はありません。 これは私が使っているすべてのものです:

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

純粋な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

これが新しい標準になるまで、古い方法を引き続き使用することができますが、一般的なライブラリや、これらのライブラリを使用していない人のための軽量の代替方法もあります。


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>


また、列挙できないプロパティを反復処理したい場合は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/>');
});


上記の答えのいずれかを使用してプロパティを繰り返し処理したい場合は、関数を含むすべてを繰り返し処理する場合は、Object.getOwnPropertyNames(obj)を使用します。Object.getOwnPropertyNames(obj)

for (let o of Object.getOwnPropertyNames(Math)) {
  console.log(o);
}

私は、時には単純な入力と出力を持つオブジェクトのすべての関数を高速にテストするためにこれを使用します。


私は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");
}




each