.map()などの高次関数はJavaScriptで内部的にどのように機能しますか?


17

今日、誰もがこの種の高次関数を使用して、少ないコードで期待できる結果を得ようとしています。しかし、これらの関数が内部でどのように機能するのか疑問に思います。

私が次のようなものを書いたとしましょう

var numbers = [16, 25, 36];
var results = numbers.map(Math.sqrt);
console.log(results); // [4, 5, 6]

'number'配列の各要素が1つずつ反復していることを知っていますが、どうやって

探してみましたが、まだ満足のいく答えが得られませんでした。


10
Array.mapのポリフィルをご覧ください
AZ_

map配列型に追加されたという関数です。この関数は、関数をパラメーターとして受け取り、配列をループしている間に呼び出されます。次に、関数呼び出しの戻り値が配列で返されます。
ssc-hrep3

mapは基本的に配列を反復するforeachのように機能し、配列のすべての要素を1つずつ取得し、各要素に特定のコマンド/操作を適用して、新しい配列にプッシュします。
Adnan Tariq

回答:


23

.mapは、コールバックを受け入れ、配列のすべての項目のコールバックを呼び出し、値を新しい配列に割り当てるメソッドです。特別なことは何もありません。自分で簡単に実装することもできます。

Array.prototype.myMap = function(callback) {
  const newArr = [];
  for (let i = 0; i < this.length; i++) {
    newArr.push(callback(this[i], i, this));
  }
  return newArr;
}

var numbers = [16, 25, 36];
var results = numbers.myMap(Math.sqrt);
console.log(results); // [4, 5, 6]

完全に仕様に準拠するには、特に、がオブジェクトであること、が呼び出し可能であること、および2番目のパラメーターが存在する場合はそれに渡される2番目のパラメーターを含むコールバックにチェックする必要thisがありますが、これらは詳細ではありません。高次関数を理解するために重要です。callback.callmyMap


8
これは私にいくつかの答えを思い出させます
Bergi

7

私はすべてのベンダーが仕様に従ってそれを実装することになっていると思います

実際の実装、たとえばV8は少し複雑になる可能性があります。最初にこの回答を参照してください。githubでv8ソースを参照することもできますが、1つの部分だけを分離して理解するのは簡単ではない場合があります。

上記の回答から引用:

V8開発者はこちら。「ビルトイン」にはいくつかの異なる実装手法があります。C++で書かれたもの、Torqueで書かれたもの、CodeStubAssemblerと呼ばれるもの、アセンブリで直接使用するものなどがあります。以前のバージョンのV8では、一部はJavaScriptで実装されていました。これらの戦略にはそれぞれ独自の長所があります(コードの複雑さ、デバッグ可能性、さまざまな状況でのパフォーマンス、バイナリサイズ、およびメモリ消費)。さらに、コードが時間とともに進化してきた歴史的な理由が常にあります。

ES2015仕様:

  1. してみましょうO ToObject(もこの値)。
  2. ReturnIfAbrupt(O)。
  3. してみましょうLEN((ゲットToLengthもO"length")を)。
  4. ReturnIfAbrupt(len)。
  5. IsCallable(callbackfn)がfalseの場合、TypeError例外をスローします。
  6. 場合thisArgが供給された、聞かせてTがあることthisArg。それ以外の場合は、T未定義にします。
  7. してみましょうA BE ArraySpeciesCreate(Olenは)。
  8. ReturnIfAbrupt(A)。
  9. してみましょうkは 0になります。
  10. 繰り返しますが、k < len
    1. してみましょうPkは ToStringメソッド(もK)。
    2. してみましょうkPresentは HasProperty(もOPkを)。
    3. ReturnIfAbrupt(kPresent)。
    4. 場合kPresentはある、その後、
      1. レッツkValueは(ゲットするOPkのを)。
      2. ReturnIfAbrupt(kValue)。
      3. してみましょうmappedValueはコール(ことcallbackfnT、« kValueKO »)。
      4. ReturnIfAbrupt(mappedValue)。
      5. してみましょうステータスが CreateDataPropertyOrThrow(もAPkはmappedValue)。
      6. ReturnIfAbrupt(status)。
    5. kを1 増やします。
  11. Aを返します。

2
私は好奇心が強いのですが、仕様の<li> list-style-typeはChromeでもFFでもコピーできません。手動で番号を書きましたか、それとも私が見逃しているより良い方法がありますか?
特定のパフォーマンス

5
@CertainPerformance笑 ソースからHTMLをコピーし、HTMLをマークダウンオンラインツールにコピーします。
sabithpocker
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.