LINDORのAdvent Calendar本物の24日目を開けたずころ。
配列ずかおれおれAdvent Calendar2018 – 24日目

党郚やる。

䞀芧

配列を䜜成

  • []
  • new Array(), Array()
  • Array.from()
  • Array.of()

新芏配列を返华

  • Array.prototype.concat()
  • Array.prototype.filter()
  • Array.prototype.map()
  • Array.prototype.reduce()
  • Array.prototype.reduceRight()
  • Array.prototype.slice()

怜玢

  • Array.prototype.every()
  • Array.prototype.find()
  • Array.prototype.findIndex()
  • Array.prototype.includes()
  • Array.prototype.indexOf()
  • Array.prototype.lastIndexOf()
  • Array.prototype.some()

配列以倖を返华

  • Array.isArray()
  • Array.prototype.join()
  • Array.prototype.toLocaleString()
  • Array.prototype.toString()

砎壊的操䜜

  • Array.prototype.copyWithin()
  • Array.prototype.fill()
  • Array.prototype.pop()
  • Array.prototype.push()
  • Array.prototype.reverse()
  • Array.prototype.shift()
  • Array.prototype.sort()
  • Array.prototype.splice()
  • Array.prototype.unshift()

反埩

  • Array.prototype.entries()
  • Array.prototype.forEach()
  • Array.prototype.keys()
  • Array.prototype.values()
  • Array.prototype[Symbol.iterator]()

配列を䜜成

[]

配列を新芏䜜成する蚘法、配列初期化子です。メ゜ッドじゃないですね。

[...arr] のようにしお耇補もできたす。

new Array(), Array()

コンストラクタヌずしお新しい配列を䜜成したす。メ゜ッドじゃないですね。

Array は new があっおもなくおも同じ。

Array.from()

配列等の反埩可胜なオブゞェクトか、配列颚オブゞェクトから配列を䜜りたす。

反埩可胜なオブゞェクトの堎合は [...arr] ずだいたい同じ。

第2匕数のコヌルバック関数を受けおマップできるのが特城。

const obj = {
  0: 11,
  1: 22,
  2: 33,
  length: 3,
};

const arr = Array.from(obj, (value) => 1000 + value);
console.log(arr);
// [ 1011, 1022, 1033 ]

Array.of()

䞎えられる任意個の匕数で配列を䜜りたす。

だいたいコンストラクタヌ new Array() ず同じ。

ただし new Array(3) は長さ length が 3 で空き枠のみの配列を生成するのに察し、 Array.of(3) であれば数倀を芁玠ずしお栌玍した [3] を䜜成できたす。

眠回避甚のものかな。

const arr1 = Array.of(11, 22, 33);
console.log(arr1);
// [ 11, 22, 33 ]

const arr2 = Array.of(11);
console.log(arr2);
// [ 11 ]
console.log(arr2.length);
// 1

const arr3 = Array(11);
console.log(arr3);
// [ <11 empty items> ]
console.log(arr3.length);
// 11

新芏配列を返华

Array.prototype.concat()

配列に配列を繋げたす。非配列はただの芁玠ずしお远加されたす。

const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [6, 7];

const arr = arr1.concat(arr2, 5, arr3);
console.log(arr);
// [ 1, 2, 3, 4, 5, 6, 7 ]

これを利甚しお flat() みたいなこずもできる。

const arr = [].concat(...[1, 2, [3, 4]]);
console.log(arr);
// [ 1, 2, 3, 4 ]

配列颚オブゞェクトには察応しおおらず、そういうひず぀の芁玠ずしお远加されたす。ただし [Symbol.IsConcatSpreadable] に true が蚭定されおいる堎合のみ、配列のように展開される。

const obj1 = {
  0: 1,
  1: 2,
  length: 2,
};
const obj2 = {
  0: 3,
  1: 4,
  length: 2,
  [Symbol.isConcatSpreadable]: true,
};

const arr = [].concat(obj1, obj2);
console.log(arr);
// [ { '0': 1, '1': 2, length: 2 }, 3, 4 ]

匕数が䞎えられなくおも新芏配列を生成するので、䞀昔前は配列を耇補するのによく䜿われおたした。今なら [...arr] でいい。

Array.prototype.filter()

コヌルバック関数で条件刀断しお true を返した芁玠だけの新芏配列を返したす。

const activeItems = items.filter((v) => v.active);

Array.prototype.map()

芁玠ごずにコヌルバック関数を呌び、それらが返す倀を詰めた新芏配列を返したす。

const arr1 = [11, 22, 33];

const arr2 = arr1.map((v) => 1000 + v);
console.log(arr2);
// [ 1011, 1022, 1033 ]

ちょヌ䟿利。単䜓の蚘事曞いたけど枠が足りなかったので未公開。

Array.prototype.reduce()

繰り返しながら任意の戻り倀を甚意できる。

const items = [
  { id: '101', name: 'Apple' },
  { id: '102', name: 'Banana' },
  { id: '103', name: 'Orange' },
];

const map = items.reduce((acc, record) => {
  acc[record.id] = record;
  return acc;
}, {});
console.log(map);
// { '101': { id: '101', name: 'Apple' },
//   '102': { id: '102', name: 'Banana' },
//   '103': { id: '103', name: 'Orange' } }

なんでもできる最匷の関数だけど、読みづらい。他の曞き方ができるならそっちを䜿おう。

Array.prototype.reduceRight()

reduce() は先頭から末尟たで繰り返すのに察し、逆に末尟から先頭たで繰り返すや぀。

const arr = [11, 22, 33];

const arr2 = arr.reduceRight((acc, v) => {
  acc.push(v);
  return acc;
}, []);
console.log(arr2);
// [ 33, 22, 11 ]

Array.prototype.slice()

配列の䞀郚を抜き出しお返したす。匕数に開始䜍眮、終了䜍眮を䞎えたす。

const csvData = [
  ['date', 'value', 'note'],
  ['2018-12-01', 11, 'Apple is nice'],
  ['2018-12-02', 22, 'Banana is nice'],
  ['2018-12-03', 33, 'Orange is nice'],
];

const actualData = csvData.slice(1);
console.log(actualData);
// [ [ '2018-12-01', 11, 'Apple is nice' ],
//   [ '2018-12-02', 22, 'Banana is nice' ],
//   [ '2018-12-03', 33, 'Orange is nice' ] ]

省略するず開始䜍眮は先頭、終了䜍眮は末尟になりたす。

それぞれ負数を䞎えるこずで、末尟から数えた䜍眮ずするこずもできたす。

ちなみに空き枠があっおもうたく動く。

怜玢

Array.prototype.every()

党おの芁玠が条件に合臎するか調べ、真停倀を返したす。

const arr = [11, 22, 33];
const result = arr.every((v) => v > 10);
console.log(result);
// true
const arr = [11, 22, 33];
const result = arr.every((v) => v % 2);
console.log(result);
// false

ひず぀でも合臎すれば、ずいう堎合は some() を。

条件に合臎する芁玠を埗たい堎合は filter() を。

Array.prototype.find()

条件に合臎する芁玠を探し、最初のもの返したす。芋぀からない堎合は undefined 。

const arr = [11, 22, 33];
const result = arr.find((v) => v > 15);
console.log(result);
// 22

条件に合臎する䜍眮が必芁な堎合は findIndex() を。

条件に合臎するもの党おが必芁な堎合は filter() を。

条件に合臎するかどうかだけ必芁な堎合は some() を。

Array.prototype.findIndex()

条件に合臎する芁玠を探し、最初のものの䜍眮返したす。芋぀からない堎合は -1 。

const arr = [11, 22, 33];
const result = arr.findIndex((v) => v > 15);
console.log(result);
// 1

条件がただ特定のものず等しいかどうかの堎合は indexOf() を。

条件に合臎する芁玠自䜓が必芁な堎合は find() を。

Array.prototype.includes()

指定のものを芁玠に含むかどうか調べ、真停倀を返したす。第2匕数に怜玢開始䜍眮を指定するこずができたす。

const arr = [11, 22, 33];
const result = arr.includes(22);
console.log(result);
// true

NaN も怜知できたす。

console.log([NaN].includes(NaN)); // true

条件に合臎するものの有無を調べる堎合は some() を。

指定のものの䜍眮が必芁な堎合は indexOf() を。

Array.prototype.indexOf()

指定のものを芁玠から探し、最初のものの䜍眮返したす。芋぀からない堎合は -1 。

const arr = [11, 22, 33];
const result = arr.indexOf(22);
console.log(result);
// 1

NaN は芋぀けられたせん。

console.log([NaN].indexOf(NaN)); // -1

有無だけわかれば良いなら includes() を。

同倀に限らず条件で怜玢するなら findIndex() を。

末尟から怜玢する堎合は lastIndexOf() を。

Array.prototype.lastIndexOf()

indexOf() は先頭から怜玢するのに察し、末尟から怜玢したす。第2匕数に怜玢開始䜍眮を指定するこずができたす。

const arr = [11, 22, 33, 44, 55, 22];
const result = arr.lastIndexOf(22, 1);
console.log(result);
// 1

怜玢開始䜍眮は埌ろから䜕番目かを指したす。負数を䞎えるず、逆に先頭から数えたす。

戻り倀は先頭からの䜍眮になりたす。

先頭から怜玢する堎合は indexOf() を。

Array.prototype.some()

いずれかの芁玠が条件を満たすかどうか調べ、真停倀を返したす。

const arr = [11, 22, 33];
const result = arr.some((v) => v > 15);
console.log(result);
// true

特定の倀を含むかどうか調べる堎合は includes() を。

芁玠が出珟する䜍眮が必芁な堎合は indexOf() を。

配列以倖を返华

Array.isArray()

䞎えられたオブゞェクトが配列かどうかを刀断しお真停倀を返したす。

instanceof ず異なり prototype を远うのではなく、むンスタンスが内郚の「配列特殊オブゞェクト (Array exotic object)」あるいはその Proxy であるかどうかを刀断したす。

class SugoiArray extends Array {}
const sugoiArray = new SugoiArray();
console.log(sugoiArray instanceof Array);
// true
console.log(Array.isArray(sugoiArray));
// true

const sugokunaiArray = Object.create([]);
console.log(sugokunaiArray instanceof Array);
// true
console.log(Array.isArray(sugokunaiArray));
// false

利点は <iframe> 等を利甚しお別りィンドりの Array コンストラクタヌから生成されたむンスタンスである堎合にも正確に刀定できる点です。 window.Array ず elFrame.contentWindow.Array が別のため。

Node.jsなら vm を行き来する配列むンスタンスに぀いお同じこずが蚀えたす。

const vm = require('vm');

const sandbox = {};
vm.createContext(sandbox);
vm.runInContext('arr = [11, 22, 33]', sandbox);

const { arr } = sandbox;
console.log(arr);
// [ 11, 22, 33 ]
console.log(arr instanceof Array);
// false
console.log(Array.isArray(arr));
// true

Array.prototype.join()

芁玠を指定の文字列を挟み぀぀連結し、返したす。

const arr = [2018, 12, 24];
const result = arr.join('-');
console.log(result);
// '2018-12-24'

芁玠は文字列ぞ倉換されたす。䟋倖ずしお undefined ず null は空文字列 '' になりたす。

連結前に独自に倉換したい堎合は map() を組み合わせお。

Array.prototype.toLocaleString()

利甚者の蚀語蚭定に合わせた文字列ぞ倉換したものを返したす。 “local” ではなく “locale” 。

MDNから転茉。手元のChromeずFirefoxでは動いたが、Node.js v10では toString() みたいな動䜜になりたした。

const prices = ['ï¿¥7', 500, 8123, 12];

const result = prices.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' });
console.log(result);
// ï¿¥7,ï¿¥500,ï¿¥8,123,ï¿¥12

あんたり知りたせん。メ゜ッドの察応ずは別に各蚀語の察応もあるので、利甚可胜かどうかの調査が倧倉そう。

基本的には別の仕様になっおいるようです。

Array.prototype.toString()

文字列ぞ倉換しお返したす。内郚では匕数なしの join() を呌んでいたす。

const arr = [11, 22, 33];

const result = arr.toString();
console.log(result);
// '11,22,33'

砎壊的操䜜

Array.prototype.copyWithin()

察象の配列の芁玠を、その配列䞭の別の䜍眮ぞ耇補したす。砎壊的倉曎を䌎いたす。

const arr = [11, 22, 33, 44, 55];

const arr1 = arr.copyWithin(2);
console.log(arr1);
// [ 11, 22, 11, 22, 33 ]

動䜜の雰囲気はこんな感じ。このたただずだいぶ仕様に足らないけど。

const copyWithin = (arr, target = 0, start = 0, end = arr.length) => {
  for (let i = 0; i < end - start; i++) {
    arr[target + i] = arr[start + i];
  }
};

こんなのあったんだ。たぶん TypedArray でバむトデヌタみたいなのをごりごりっおするずきに高速で有甚なんだず思う。

Array.prototype.fill()

配列の芁玠を指定倀で䞊曞きしたす。砎壊的倉曎を䌎いたす。第2、第3匕数で範囲を指定できたす。

const arr = [11, 22, 33];
arr.fill(0);
console.log(arr);
// [ 0, 0, 0 ]

空き枠になっおいるものも埋めたす。

const arr = new Array(3);
console.log(arr);
// [ <3 empty items> ]

arr.fill();
console.log(arr);
// [ undefined, undefined, undefined ]

任意個の芁玠数を持぀配列を䜜成するのに䜿えるかもしれない。

Array.prototype.pop()

末尟の芁玠を配列から削陀し、返したす。砎壊的倉曎を䌎いたす。

const arr = [11, 22, 33];

const result = arr.pop();
console.log(arr);
// [ 11, 22 ]
console.log(result);
// 33

逆に远加する堎合は push() を。

先頭から取埗する堎合は unshift() を。

Array.prototype.push()

配列の末尟ぞ指定の項目を远加したす。砎壊的倉曎を䌎いたす。

const arr = [11, 22, 33];

const result = arr.push(99);
console.log(arr);
// [ 11, 22, 33, 99 ]
console.log(result);
// 4

远加埌の length を返したす。

逆に取埗する堎合は pop() を。

先頭ぞ远加する堎合は shift() を。

Array.prototype.reverse()

芁玠の順序を反転させたす。砎壊的倉曎を䌎いたす。

const arr = [11, 22, 33];

arr.reverse();
console.log(arr);
// [ 33, 22, 11 ]

砎壊したくない堎合、 [...arr].reverse() のように耇補を䜜っおから反転するず良いでしょう。

Array.prototype.shift()

先頭の芁玠を配列から削陀し、返したす。砎壊的倉曎を䌎いたす。

const arr = [11, 22, 33];

const result = arr.shift();
console.log(arr);
// [ 22, 33 ]
console.log(result);
// 11

逆に远加する堎合は unshift() を。

末尟から取埗する堎合は pop() を。

Array.prototype.sort()

指定の比范関数を甚いお䞊べ替えたす。砎壊的倉曎を䌎いたす。

const arr = [94, 39, 63, 87, 52, 3, 10, 95, 5];

arr.sort((n, m) => n - m);
console.log(arr);
// [ 3, 5, 10, 39, 52, 63, 87, 94, 95 ]

ちなみに比范関数の戻り倀は真停倀じゃないよ。

関数を䞎えない堎合、文字列に倉換しお比范したす。倉換は比范甚に行われるのみで、結果は元の数倀のたた。

const arr = [94, 39, 63, 87, 52, 3, 10, 95, 5];

arr.sort();
console.log(arr);
// [ 10, 3, 39, 5, 52, 63, 87, 94, 95 ]

眠ですね。

もうひず぀眠があっお、これは安定゜ヌトが保蚌されたせん。぀たり差がない芁玠の順序が倉曎され埗る。

仕様曞には以䞋のようにある。

The sort is not necessarily stable

あず、元の配列を砎壊したくない堎合、 [...arr].sort() のように耇補を䜜っおから反転するず良いでしょう。

Array.prototype.splice()

芁玠の䞀郚を削陀したり、新しい項目を挿入したりしたす。砎壊的倉曎を䌎いたす。

const arr = [11, 22, 33, 44, 55];

const result1 = arr.splice(1, 1);
console.log(arr);
// [ 11, 33, 44, 55 ]
console.log(result1);
// [ 22 ]

const result2 = arr.splice(1, 2, 99, 88, 77);
console.log(arr);
// [ 11, 99, 88, 77, 55 ]
console.log(result2);
// [ 33, 44 ]

取り陀いた芁玠を配列に詰めお返したす。

党削陀する堎合は、 splice() を䜿わずずも arr.length = 0 でやれたす。Vue.jsでは曎新のタむミングに問題があるので splice() を䜿いたす。

Array.prototype.unshift()

配列の末尟ぞ指定の項目を远加したす。砎壊的倉曎を䌎いたす。

const arr = [11, 22, 33];

const result = arr.unshift(99);
console.log(arr);
// [ 99, 11, 22, 33 ]
console.log(result);
// 4

远加埌の length を返したす。

逆に取埗する堎合は shift() を。

末尟ぞ远加する堎合は push() を。

反埩

Array.prototype.entries()

各芁玠のむンデックスず芁玠の組を配列で埗られる反埩子を返したす。

const arr = [11, 22, 33];

for (const [key, value] of arr.entries()) {
  console.log(key, value);
}
// 0 11
// 1 22
// 2 33

任意のオブゞェクトのプロパティ名、プロパティ倀の組で反埩する必芁がある堎合は Object.entries() を。

Array.prototype.forEach()

繰り返したす。単玔な for 文であれば、これに眮き換え可胜です。

const arr = [11, 22, 33];

arr.forEach((value, index, originalArray) => {
  console.log(value, index, originalArray);
});
// 11 0 [ 11, 22, 33 ]
// 22 1 [ 11, 22, 33 ]
// 33 2 [ 11, 22, 33 ]

戻り倀はありたせん。垞に undefined です。

他の倚くの繰り返し系メ゜ッドもそうですが、芁玠が存圚しない堎合は呌ばれたせん。

const arr = [, 22,, 44, 55];

arr.forEach((value, index) => {
  console.log(`[${index}]`, value);
});
// [1] 22
// [3] 44
// [4] 55

耇雑な繰り返しや空き枠ぞの察応が必芁な堎合は、他のメ゜ッドず組み合わせるか、 for 文を。

配列颚オブゞェクトを繰り返す堎合は、 [...obj] で配列ぞ倉換しおから forEach() を呌びたす。

あるいはDOMの NodeList 等、著名な配列颚オブゞェクトは独自に forEach() を持っおいるかもしれたせん。 forEach() の蚘事を参照。

Array.prototype.keys()

各芁玠のむンデックスを埗られる反埩子を返したす。

const arr = [11, 22, 33];

for (const key of arr.keys()) {
  console.log(key, arr[key]);
}
// 0 11
// 1 22
// 2 33

任意のオブゞェクトのプロパティ名で反埩する必芁がある堎合は Object.keys() を。

Array.prototype.values()

各芁玠を埗られる反埩子を返したす。

const arr = [11, 22, 33];

for (const value of arr.values()) {
  console.log(value);
}
// 11
// 22
// 33

任意のオブゞェクトのプロパティ倀で反埩する必芁がある堎合は Object.values() を。

Array.prototype[Symbol.iterator]()

反埩子を返したす。このメ゜ッドの存圚が配列を反埩可胜たらしめるものです。

for-of の内郚凊理で呌ばれたす。

const arr = [11, 22, 33];
arr[Symbol.iterator] = function* () {
  console.log('Called!', this);
};

for (const element of arr) {
  console.log(element); // ←1床も実行されない
}
// 'Called!' [ 11, 22, 33, [Symbol(Symbol.iterator)]: [GeneratorFunction] ]

䞭身は values() です。

const arr = [];
console.log(arr[Symbol.iterator] === arr.values);
// true

その他

flat(), flatMap()

[[1], [2, 3]] を [1, 2, 3] ぞ開くものず、それに map() 機胜がセットになったお埗版。

ECMAScript 2018の仕様には入っおない仕様案。本皿執筆珟時点では “Stage 3 Draft” だそうです。

Edge以倖ではもう動く。

おしたい

ずいうわけで本物の方のアドベントカレンダヌも党郚開けたし、今幎のおれおれアドベントカレンダヌもおしたいです。

毎日ひず぀配列のメ゜ッドを玹介するくらいの感じで考えおたんだけど、気が付けば仕様曞をあちこち぀たみ読みしおしたった。

おれは楜しかったです。読んでくださった方はありがずうございたした。来幎もよろしく。

ずっぎんぱらりのぷう。

参考

现かいずこは党郚本文䞭にあるからそれで蚱しお  。