JavaScriptオブジェクトを反復する方法は?


422

JavaScriptにオブジェクトがあります。

{
    abc: '...',
    bca: '...',
    zzz: '...',
    xxx: '...',
    ccc: '...',
    // ...
}

forループを使用してそのプロパティを取得したいと考えています。そして、それを部分的に反復したいと思います(一度にすべてのオブジェクトプロパティではありません)。

単純な配列を使用すると、標準forループでそれを行うことができます。

for (i = 0; i < 100; i++) { ... } // first part
for (i = 100; i < 300; i++) { ... } // second
for (i = 300; i < arr.length; i++) { ... } // last

しかし、オブジェクトでそれを行う方法は?


22
オブジェクトのプロパティは順番に格納されないことに注意してください。オブジェクトを繰り返し処理する場合、オブジェクトが表示される順序は保証されません。
James Allardice 2013年

回答:


850

ほとんどのオブジェクトでは、次を使用しますfor .. in

for (let key in yourobject) {
  console.log(key, yourobject[key]);
}

ES6でキーと値の両方が同時に必要な場合は、

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

継承されたプロパティのロギングを回避するには、hasOwnPropertyで確認します。

for (let key in yourobject) {
   if (yourobject.hasOwnProperty(key)) {
      console.log(key, yourobject[key]);
   }
}

hasOwnProperty単純なオブジェクト(たとえば、で作成したオブジェクト)を使用している場合は、キーを反復するときに確認する必要はありません{}

このMDNドキュメントでは、オブジェクトとそのプロパティを処理する方法をより一般的に説明しています。

「チャンクで」行う場合は、配列内のキーを抽出するのが最適です。順序は保証されていないので、これは適切な方法です。最新のブラウザでは、

let keys = Object.keys(yourobject);

互換性を高めるには、次のようにします。

 let keys = [];
 for (let key in yourobject) {      
     if (yourobject.hasOwnProperty(key)) keys.push(key);
 }

次に、インデックスでプロパティを反復できますyourobject[keys[i]]

for (let i=300; i < keys.length && i < 600; i++) { 
   console.log(keys[i], yourobject[keys[i]]);
}

3
OPは、これを単一のループ内のすべてのキーではなく、チャンクで実行したいと考えています。
パウェル

はい。1つのループで完全なオブジェクトではありません。
nkuhta 2013年

2
@Cerbrus OPは、配列を部分的に反復する方法をすでに知っています。keys指定されたコードから使用するだけで十分です。
ヨシ

2
@Cerbrusコメントする前にお読みください!「互換性を高めるには、これを行う方がよい」で明確でないことは何ですか?
DenysSéguret2013年

2
@ am05mhz言ったように、ほとんどのオブジェクトでは役に立たない。しかし、すべてではありません。これを試してください:jsbin.com/hirivubuta/1/edit?js,console,output
DenysSéguretSep

61

これが、最新のブラウザーの別の反復ソリューションです。

Object.keys(obj)
  .filter((k, i) => i >= 100 && i < 300)
  .forEach(k => console.log(obj[k]));

またはフィルター機能なし:

Object.keys(obj).forEach((k, i) => {
    if (i >= 100 && i < 300) {
        console.log(obj[k]);
    }
});

ただし、JavaScriptオブジェクトのプロパティは並べ替えられていない、つまり順序​​がないことを考慮する必要があります。


ループを解除すると、次回はオブジェクトの最初から開始されるため、正しくありません。
nkuhta 2013年

21

Object.entriesあなたを使ってこのようなことをします。

 // array like object with random key ordering
 const anObj = { 100: 'a', 2: 'b', 7: 'c' };
 console.log(Object.entries(anObj)); // [ ['2', 'b'],['7', 'c'],['100', 'a'] ]

Object.entries()メソッドは、指定されたオブジェクト自体の列挙可能なプロパティ[キー、値]の配列を返します

だから、オブジェクトを反復処理して持つことができるkeyvalue、オブジェクトのそれぞれについて、このようなものを取得します。

const anObj = { 100: 'a', 2: 'b', 7: 'c' };
Object.entries(anObj).map(obj => {
   const key   = obj[0];
   const value = obj[1];

   // do whatever you want with those values.
});

またはこのように

// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});

参考として、オブジェクトエントリの MDNドキュメントを参照してください。


17

ES6 / ES2015の新機能により、ハッシュを反復処理するためにオブジェクトを使用する必要がなくなりました。マップを使用できます。JavaScriptマップはキーを挿入順に保持します。つまり、hasOwnPropertyをチェックしなくてもキーを反復処理できます。これは常に本当にハックでした。

マップを反復する:

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

for (var key of myMap.keys()) {
  console.log(key);
}
// Will show 2 logs; first with "0" and second with "1"

for (var value of myMap.values()) {
  console.log(value);
}
// Will show 2 logs; first with "zero" and second with "one"

for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

またはforEachを使用:

myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

1
forEachが
優先されます

14

反復時にキーと値が必要な場合は、Object ... entriesでfor ... ofループを使用できます。

const myObj = {a: 1, b: 2}

for (let [key, value] of Object.entries(myObj)) {
    console.log(`key=${key} value=${value}`)
}

// output: 
// key=a value=1
// key=b value=2

7

これを行う唯一の信頼できる方法は、オブジェクトデータを2つの配列に保存することです。1つはキーで、もう1つはデータ用です。

var keys = [];
var data = [];
for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        keys.push(key);
        data.push(obj[key]); // Not necessary, but cleaner, in my opinion. See the example below.
    }
}

その後、通常どおりに配列を反復処理できます。

for(var i = 0; i < 100; i++){
    console.log(keys[i], data[i]);
    //or
    console.log(keys[i], obj[keys[i]]); // harder to read, I think.
}
for(var i = 100; i < 300; i++){
    console.log(keys[i], data[i]);
}

Object.keys(obj)IE 9以上なので、私はを使用していません。


3

->オブジェクトの配列のキーを使用してJavaScriptオブジェクトを反復処理した場合

Object.keys(Array).forEach(key => {

 console.log('key',key)

})

1

オブジェクト全体を一度に繰り返し処理したい場合は、for inループを使用できます。

for (var i in obj) {
  ...
}

しかし、実際にはオブジェクトをパーツに分割したい場合はできません。オブジェクトのプロパティが指定された順序であるという保証はありません。したがって、2つの解決策が考えられます。

その1つは、既に読み込まれたプロパティを「削除」することです。

var i = 0;
for (var key in obj) {
    console.log(obj[key]);
    delete obj[key];
    if ( ++i > 300) break;
}

私が考えることができる別の解決策は、オブジェクトの代わりに配列の配列を使用することです:

var obj = [['key1', 'value1'], ['key2', 'value2']];

その後、標準forループが機能します。


1

最後に、オブジェクト、文字列、配列、TypedArrays、マップ、セット(すべてのIterables)を反復処理するための統一されたインターフェースを備えた便利なユーティリティ関数を思いつきました。

const iterate = require('@a-z/iterate-it');
const obj = { a: 1, b: 2, c: 3 };

iterate(obj, (value, key) => console.log(key, value)); 
// a 1
// b 2
// c 3

https://github.com/alrik/iterate-javascript


1

あなたはlodashを使用して試すことができます- モジュールの高速化、パフォーマンス、および追加の jsを提供する最新のJavaScriptユーティリティライブラリ:オブジェクトの高速反復:-

var  users  =   {
    'fred':     { 
        'user':   'fred',
            'age':  40 
    },
    'pebbles':  { 
        'user':   'pebbles',
         'age':  1 
    }
}; 
_.mapValues(users,  function(o)  { 
    return  o.age; 
});
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
// The `_.property` iteratee shorthand.
console.log(_.mapValues(users,  'age')); // returns age property & value 
console.log(_.mapValues(users,  'user')); // returns user property & value 
console.log(_.mapValues(users)); // returns all objects 
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash-compat/3.10.2/lodash.js"></script>


1

オブジェクトの反復には、通常for..inループを使用します。この構造は、プロトタイプ継承を介して継承されたものを含む、列挙可能なすべてのプロパティをループします。例えば:

let obj = {
  prop1: '1',
  prop2: '2'
}

for(let el in obj) {
  console.log(el);
  console.log(obj[el]);
}

ただし、for..in列挙可能なすべての要素をループするため、反復をチャンクに分割することはできません。これを実現するには、組み込みObject.keys()関数を使用して、配列内のオブジェクトのすべてのキーを取得します。次に、反復を複数のforループに分割し、keys配列を使用してプロパティにアクセスできます。例えば:

let obj = {
  prop1: '1',
  prop2: '2',
  prop3: '3',
  prop4: '4',
};

const keys = Object.keys(obj);
console.log(keys);


for (let i = 0; i < 2; i++) {
  console.log(obj[keys[i]]);
}


for (let i = 2; i < 4; i++) {
  console.log(obj[keys[i]]);
}


0
var Dictionary = {
  If: {
    you: {
      can: '',
      make: ''
    },
    sense: ''
  },
  of: {
    the: {
      sentence: {
        it: '',
        worked: ''
      }
    }
  }
};

function Iterate(obj) {
  for (prop in obj) {
    if (obj.hasOwnProperty(prop) && isNaN(prop)) {
      console.log(prop + ': ' + obj[prop]);
      Iterate(obj[prop]);
    }
  }
}
Iterate(Dictionary);

1
実は違う。これObjectは、sが正しい順序であることを意味します。そうではありません。If you can make sense of the sentence it worked実装の詳細のためにのみ機能します。動作することは保証されていません。また、関数と変数をTitleCaseしないでください。それはclasses のためです。
Florian Wendelborn 2017

0

本当にPITAは標準のJavaScriptの一部ではありません。

/**
 * Iterates the keys and values of an object.  Object.keys is used to extract the keys.
 * @param object The object to iterate
 * @param fn (value,key)=>{}
 */
function objectForEach(object, fn) {
    Object.keys(object).forEach(key => {
        fn(object[key],key, object)
    })
}

注:コールバックパラメーターを(value、key)に切り替え、APIを他のAPIと整合させるために3番目のオブジェクトを追加しました。

このように使う

const o = {a:1, b:true};
objectForEach(o, (value, key, obj)=>{
    // do something
});

1
最初の文のステートメントだけに賛成票を投じました。値が最初のパラメーター、インデックスまたはキーの2番目のパラメーター、およびオブジェクトの3番目のパラメーターであれば、配列forEach()のようにする方がよいでしょう。ロダッシュをお勧めします。
契約は私が正しいと言う

(値、キー)順序の考え方が好きです。これが、Vueなどのライブラリが行う方法でもあります。オブジェクトはコンテキストなので、最初のパラメーターとして属していると考えています。これは関数型プログラミングの標準です。
Steven Spungin

ECMA-262が配列をforEach()、map()、reduce()、filter()を持つオブジェクトとして定義していない場合、これらはすべて[値、インデックス、配列]のコールバックを受け取るコールバックを取ります。 。JSのオブジェクトは、単なる別のコレクションとして理解できます。そして、これらのメソッドは、[値、キー|インデックス、コンテキスト]のパラメーターで統合されます(これはロダッシュとアンダースコアが行っていることです)。私の意見では、この「統一されたコレクション」プロトコルはより強力です。また、オブジェクトコンテキストではありませんthis。コールバックには独自のコンテキストがあるため、コールバックには任意の値を設定できます。
契約によると私は正しいと

おそらく、これの代わりに仕事用の受信機を使用するべきでした。とにかく、まだPITAです。パラメータは任意の順序で歓迎します。
Steven Spungin

ああ、私たちはお互いを誤解しているようです。私はいつも、実際のobjectForEach関数ではなく、コールバックパラメータとその順序についてコメントしていました。混乱した場合は申し訳ありません。
契約は私が正しいと言う

0

はい。forループを使用してオブジェクトをループできます。ここに例があります

var myObj = {
    abc: 'ABC',
    bca: 'BCA',
    zzz: 'ZZZ',
    xxx: 'XXX',
    ccc: 'CCC',
}

var k = Object.keys (myObj);
for (var i = 0; i < k.length; i++) {
    console.log (k[i] + ": " + myObj[k[i]]);
}

注:上記の例はIE9 +でのみ機能します。こちらのObjec.keysブラウザサポートをご覧ください


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.