ECMAScript 6は、新しい配列操作方法の展望をもたらします.

6930 ワード

この文書では、ECMAScript 6が新しい配列操作方法を提供し、既存のブラウザでこれらの新しい配列特性をどのように適用するかについて説明します.
Note:コンストラクタとクラスの2つの用語を交互に使用します.
クラスメソッド配列(Array)自身が持つメソッド.
Array.from(arrayLike, mapFunc?, thisArg?)
Array.from()の基本機能は,2種類のオブジェクトを配列に変換することである.
クラス配列オブジェクト(Array-like objects)
このクラスオブジェクトには、長さとインデックスのプロパティがあります.DOMオペレータの結果はdocumentのようなクラスに属する.getElementsByClassName().
反復可能オブジェクト(Iterable objects)
このようなオブジェクトは、値を取るたびに1つの要素しか取れません.配列は、ECMAScriptの新しい配列構造、マッピング(Map)、セット(Set)のように反復可能である.
次のコードは、クラス配列オブジェクトを配列に変換する例です.
 
  
let lis = document.querySelectorAll('ul.fancy li');
Array.from(lis).forEach(function (li) {
  console.log(node);
});

querySelectorAll()の結果は配列ではなくforEach()という方法もありません.これは,この方法を使用する前に配列に変換する必要がある理由である.
アリーを通してfrom()はMapping Arrayを使用する.from()もmap()を汎用的に使用する代替選択である.
 
  
let spans = document.querySelectorAll('span.name');
// map(), generically:
let names1 = Array.prototype.map.call(spans, s => s.textContent);
// Array.from():
let names2 = Array.from(spans, s => s.textContent);

2つの方法の2番目のパラメータは、矢印関数(arrow function)です.この例ではdocument.querySelectorAll()の結果は、配列ではなくクラス配列オブジェクトです.これがmap()を直接呼び出すことができない理由です.最初の例では、forEach()を使用するためにクラス配列オブジェクトを配列に変換します.ここでは汎用法と2つのパラメータバージョンのArray.from()は、中間ステップを省略します.
Holes Array.from()は、配列に欠落している要素-ホール(holes)を無視し、未定義の要素(undefined elements)で扱われます.
 
  
> Array.from([0,,2])
[ 0, undefined, 2 ]

つまりArrayを使うことができますfrom()を使用して配列を作成または埋め込みます.
 
  
> Array.from(new Array(5), () => 'a')
[ 'a', 'a', 'a', 'a', 'a' ]
> Array.from(new Array(5), (x,i) => i)
[ 0, 1, 2, 3, 4 ]

配列を一定の値で埋めたい場合はArray.prototype.fill()(以下を参照)はより良い選択になります.1つ目は、上記の例の2つの方法である.
配列(Array)サブクラス内のfrom()別のArray.from()の使用シーンは、クラス配列オブジェクトまたは反復可能オブジェクトを配列(Array)サブクラスに変換するインスタンスです.ArrayのサブクラスMyArrayを作成し、そのようなオブジェクトをMyArrayのインスタンスに変換するには、MyArrayを簡単に使用することができます.from().これは、ECMAScript 6でコンストラクタ(constructors)が継承されるためです(親コンストラクタはその子コンストラクタのプロトタイプです).
 
  
class MyArray extends Array {
  ...
}
let instanceOfMyArray = MyArray.from(anIterable);

この機能をマッピング(mapping)と組み合わせて、結果コンストラクタを制御する場所でマッピング操作(map operation)を完了できます.
 
  
// from() �C determine the result's constructor via the receiver
// (in this case, MyArray)
let instanceOfMyArray = MyArray.from([1, 2, 3], x => x * x);
// map(): the result is always an instance of Array
let instanceOfArray   = [1, 2, 3].map(x => x * x);
Array.of(...items)

値のセットを配列に変換する場合は、配列ソーステキスト(array literal)を使用します.特に値が1つしかなく、数字がある場合、配列のコンストラクタがストライキをします.詳細については、を参照してください.
 
  
> new Array(3, 11, 8)
[ 3, 11, 8 ]
> new Array(3)
[ , ,  ,]
> new Array(3.1)
RangeError: Invalid array length

値のセットをデジタルサブコンストラクタのインスタンスに変換するには、どうすればいいですか?これがアリーof()の存在価値(配列サブコンストラクタはすべての配列メソッドを継承することを覚えておいてください.もちろんof()も含まれます).
 
  
class MyArray extends Array {
  ...
}
console.log(MyArray.of(3, 11, 8) instanceof MyArray); // true
console.log(MyArray.of(3).length === 1); // true

配列に値を包むof()はかなり便利で、Array()のような奇妙な処理はありません.でも気をつけてprototype.map()、ここに穴があります.
 
  
> ['a', 'b'].map(Array.of)
[ [ 'a', 0, [ 'a', 'b' ] ],
[ 'b', 1, [ 'a', 'b' ] ] ]
> ['a', 'b'].map(x => Array.of(x)) // better
[ [ 'a' ], [ 'b' ] ]
> ['a', 'b'].map(x => [x]) // best (in this case)
[ [ 'a' ], [ 'b' ] ]

ご覧のように、map()は3つのパラメータをコールバックに渡します.最後の2つはまたよく無視されます(詳細).
プロトタイプメソッド(Prototype methods)配列のインスタンスには、多くの新しいメソッドが使用できます.
配列内の反復(Iterating over arrays)
次の方法は、配列内の反復を完了するのに役立ちます.
 
  
Array.prototype.entries()
Array.prototype.keys()
Array.prototype.values()

以上の各メソッドは一連の値を返しますが、配列として返されません.反復器によって次々と表示されます.例を見てみましょう(Array.from()を使用して反復器の内容を配列に配置します):
 
  
> Array.from([ 'a', 'b' ].keys())
[ 0, 1 ]
> Array.from([ 'a', 'b' ].values())
[ 'a', 'b' ]
> Array.from([ 'a', 'b' ].entries())
[ [ 0, 'a' ],
[ 1, 'b' ] ]

entries()とECMAScript 6のfor-ofループを組み合わせて、反復オブジェクトをkey-valueペアに簡単に分解できます.
 
  
for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}

Note:このコードは最新のFirefoxブラウザで実行できます.t Firefox.
配列要素の検索
Array.prototype.find(predicate, thisArg?) コールバック関数を満たす最初の要素が返されます.条件を満たす要素が1つもない場合、undefinedが返されます.例:
 
  
> [6, -5, 8].find(x => x < 0)
-5
> [6, 5, 8].find(x => x < 0)
undefined
Array.prototype.findIndex(predicate, thisArg?)

コールバック関数を満たす最初の要素のインデックスが返されます.満たされていない要素が見つからない場合は、-1を返します.例:
 
  
> [6, -5, 8].findIndex(x => x < 0)
1
> [6, 5, 8].findIndex(x => x < 0)
-1

両方のfind*メソッドは、undefinedの要素に注目しないホール(holes)を無視します.コールバックの完了関数署名は次のとおりです.
predicate(element,index,array)findIndex()でNaNを探す
Array.prototype.indexOf()にはよく知られている制限があります.それはNaNを検索できないことです.一致する要素を一定の値(===)で検索するためです.
 
  
> [NaN].indexOf(NaN)
-1

findIndex()を使用すると、Objectを使用できます.is()は、このような問題は発生しません.
 
  
> [NaN].findIndex(y => Object.is(NaN, y))
0

ヘルプ関数elemIs()を作成するには、より一般的な方法を使用することもできます.
 
  
> function elemIs(x) { return Object.is.bind(Object, x) }
> [NaN].findIndex(elemIs(NaN))
0
Array.prototype.fill(value, start?, end?)

与えられた数値で配列を入力します.
 
  
> ['a', 'b', 'c'].fill(7)
[ 7, 7, 7 ]

ホール(Holes)にも特別な扱いはありません.
 
  
> new Array(3).fill(7)
[ 7, 7, 7 ]

充填の開始と終了を制限することもできます.
 
  
> ['a', 'b', 'c'].fill(7, 1, 2)
[ 'a', 7, 'c' ]

新しい配列方法はいつ使えますか?ブラウザで使用できる方法はいくつかあります.