JavaScript

JavaScript で [key, value] のループと分割代入を使ったループ

1. 調べようと思ったきっかけ

参考「非推奨の機能、廃止された機能 - JavaScript | MDN

何となく上のページを読んでいたら、

  • 分割代入型 for...in は非推奨です。代わりに for...of を使用してください。

とあったのですが、for...in のページを見ても「分割代入型 for...in」が何なのか書いてなかったので、気になって調べてみました。

(実は最近まで for...in が非推奨だと勘違いしていました… (汗

2. 分割代入型 for...in (非推奨)

普通の for...in は非推奨ではないですが、「分割代入型 for...in」は非推奨です。

分割代入型 for...in (非推奨)
// Array
let array = [['a', 1], ['b', 2], ['c', 3]];

console.log('array');
for (let [key, value] in array) { // ★
    console.log({key, value});
}

// Map
let map = new Map([['a', 1], ['b', 2], ['c', 3]]);

console.log('map');
for (let [key, value] in map) { // ★
    console.log({key, value});
}

// Object
let object = {'a': 1, 'b': 2, 'c': 3};

console.log('object');
for (let [key, value] in object) { // ★
    console.log({key, value});
}

(もちろん [key, value] 以外にもコードがあり得ます)

※実行環境によりますが、このコードは正しく動作しないと思った方が良いです。

3. 分割代入型 for...of

こちらは使って大丈夫です。

(for...ofIterator を使った方法が非推奨、という情報がありますが、ここで言っているのは Iterator を使わない方法です)

3.1. Array

配列の要素を分割代入して使いたいときはそのまま回せます。

分割代入型 for...of
// Array
let array = [['a', 1], ['b', 2], ['c', 3]];

console.log('array');
for (let [key, value] of array) { // ★
    console.log({key, value});
}

3.2. Array - Array.prototype.entries()

配列のインデックスを key にして回したいときは Array.prototype.entries() を使います。

分割代入型 for...of
// Array 2
let array2 = ['a', 'b', 'c'];

console.log('array2');
for (let [key, value] of array2.entries()) { // ★
    console.log({key, value});
}

3.3. Map

Map はそのまま回すことができます。

分割代入型 for...of
// Map
let map = new Map([['a', 1], ['b', 2], ['c', 3]]);

console.log('map');
for (let [key, value] of map) { // ★
    console.log({key, value});
}

参考「Map で反復する - for...of - JavaScript | MDN

3.4. Object - Object.entries()

Object で Map と同じようなことがしたいときは Object.entries() を使います。

分割代入型 for...of
// Object
let object = {'a': 1, 'b': 2, 'c': 3};

console.log('object');
for (let [key, value] of Object.entries(obj)) { // ★
    console.log({key, value});
}

Object.entries() は、ES8 の機能です。
日本語版の MDN だと「これは実験段階の機能です。」と出てきますが、英語版だと取り除かれています。

参考「Object.entries() - JavaScript | MDN」(日本語版)
参考「Object.entries() - JavaScript | MDN」(英語版)

Object.entries()Array.prototype.entries() とは違い、static メソッドです。

4. forEach()

4.1. Array - 分割代入

分割代入は関数の引数でも使えます。
ただし、アロー関数の場合、引数の括弧 () を省略できません。

forEach
// Array
let array = [['a', 1], ['b', 2], ['c', 3]];

console.log('array');
array.forEach(([key, value]) => { // ★
    console.log({key, value});
});

4.2. Array

インデックスは普通の forEach() で取得できます。

forEach
// Array 2
let array2 = ['a', 'b', 'c'];

console.log('array2');
array2.forEach((value, key) => { // ★
    console.log({key, value});
});

Array.prototype.entries()forEach() を使うことはできません。

4.3. Map

Map もそのまま forEach() で回せます。

forEach
// Map
let map = new Map([['a', 1], ['b', 2], ['c', 3]]);

console.log('map');
map.forEach((value, key) => { // ★
    console.log({key, value});
});

4.4. Object - Object.entries() - 分割代入

Array.prototype.entries()forEach() で回せませんが、Object.entries() は回せます。

forEach
// Object
let object = {'a': 1, 'b': 2, 'c': 3};

console.log('object');
Object.entries(object).forEach(([key, value]) => { // ★
    console.log({key, value});
});

5. key だけを回して value を取得

5.1. 普通の for...in

普通の for...in で key だけ取得して let value = foo[key]; のように value を取得する。

5.2. key 配列を使う

以下のコードで key 配列を取得し、for...offorEach() で key ごとに回し、let value = foo[key]; のように value を取得する。

Object.keys(array);
Map.prototype.keys();
Object.keys(object);