ECMAScript 5.1 仕様のセクション 15.4.4.20では、次のように定義Array.prototype.filter(callbackfn, thisArg)
されています。
callbackfn
true
は、3 つの引数を受け取り、ブール値または
に強制可能な値を返す関数でなければなりませんfalse
。は、配列内の各要素に対して昇順で 1 回filter
呼び出し、すべての値の新しい配列を作成します。実際に存在する配列の要素に対してのみ呼び出されます。配列の要素が欠落している場合は呼び出されません。callbackfn
callbackfn
true
callbackfn
パラメータが指定されている
場合は、 の各呼び出しの値thisArg
として使用されます。指定されていない場合は、
代わりに が使用されます。this
callbackfn
undefined
callbackfn
要素の値、要素のインデックス、およびトラバースされるオブジェクトの 3 つの引数で呼び出されます。
filter
が呼び出されたオブジェクトを直接変更することはありませんが、オブジェクトは への呼び出しによって変更される場合がありますcallbackfn
。
フィルタによって処理される要素の範囲は、 への最初の呼び出しの前に設定されますcallbackfn
。filter の呼び出しが開始された後に配列に追加された要素は、 によってアクセスされませんcallbackfn
。配列の既存の要素が変更された場合、渡され
callbackfn
た値はフィルターがアクセスしたときの値になります。filter の呼び出しが開始された後、アクセスされる前に削除された要素はアクセスされません。
それ自体がすでに大変な作業です。ECMAScript エンジンが実行する必要がある多くのステップ。
続けて、次のように言います。
filter メソッドが 1 つまたは 2 つの引数で呼び出されると、次の手順が実行されます。
引数として値を渡してO
呼び出した結果をみましょう。引数を指定して の内部メソッドを呼び出した結果をとします。させてToObject
this
lenValue
[[Get]]
O
length
len
ToUint32(lenValue)
. IsCallable(callbackfn) が false の場合、TypeError 例外をスローします。thisArg が指定された場合、T を thisArg とします。それ以外の場合は、T を未定義にします。A を式 new Array() によって作成されたかのように作成された新しい配列とします。ここで、Array はその名前の標準の組み込みコンストラクターです。k を 0 とします。0 とします。繰り返しますが、k < len Pk を ToString(k) とします。kPresent を、O の [[HasProperty]] 内部メソッドを引数 Pk で呼び出した結果とする。kPresent が true の場合、kValue を引数 Pk で O の [[Get]] 内部メソッドを呼び出した結果とします。T を this 値として、kValue、k、および O を含む引数リストを使用して、callbackfn の [[Call]] 内部メソッドを呼び出した結果を selected とします。ToBoolean(selected) が true の場合、[[DefineOwnProperty]] を呼び出します。引数 ToString(to) を持つ A の内部メソッド、プロパティ記述子 {[[Value]]: kValue、[[Writable]]: true、[[Enumerable]]: true、[[Configurable]]: true}、および false。を 1 ずつ増やします。k を 1 増やします。A を返します。
filter メソッドの長さプロパティは 1 です。
注意 フィルタ関数は意図的に汎用的です。この値が Array オブジェクトである必要はありません。したがって、メソッドとして使用するために他の種類のオブジェクトに転送できます。フィルター関数をホスト オブジェクトに正常に適用できるかどうかは、実装に依存します。
このアルゴリズムに関する注意事項:
- 述語関数がデータを変更するのを防ぎます
- オプションで、述語関数の実行コンテキストを設定します
- 配列内の削除された値とギャップを無視します
多くの場合、これらは必要ありません。そのため、独自のメソッドを作成する場合filter
、ほとんどの場合、これらの手順を実行することさえ気にしません。
すべての ES5.1 準拠の JavaScript エンジンは、そのアルゴリズムに準拠する必要があるため、 を使用するたびにこれらすべての手順を実行する必要がありますArray#filter
。
これらのステップの一部のみを実行するカスタム作成メソッドの方が高速であることは驚くべきことではありません :)
独自のfilter
関数を作成する場合、上記のアルゴリズムほど複雑ではない可能性があります。ユースケースによっては、配列をフィルタリングするためだけに必要ない場合があるため、配列をオブジェクトにまったく変換しない可能性があります。