Wie funktionieren Funktionen höherer Ordnung wie .map () intern in JavaScript?

17

Heutzutage versucht jeder, diese Art von Funktionen höherer Ordnung zu verwenden, um vielversprechende Ergebnisse mit weniger Code zu erzielen. Aber ich frage mich, wie diese Funktionen intern funktionieren.

Angenommen, ich schreibe so etwas

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

Ich weiß, dass jedes Element des 'number'-Arrays einzeln iteriert, aber wie ?

Ich habe versucht, danach zu suchen, aber ich habe noch keine zufriedenstellende Antwort erhalten.

Bilal Khan
quelle
10
Schauen Sie sich polyfil von Array.map
AZ_
Es ist eine aufgerufene Funktion, mapdie dem Typ Array hinzugefügt wurde. Diese Funktion übernimmt eine Funktion als Parameter, die dann beim Durchlaufen des Arrays aufgerufen wird. Die Rückgabewerte der Funktionsaufrufe werden dann in einem Array zurückgegeben.
ssc-hrep3
map funktioniert im Grunde wie foreach, um das Array zu iterieren. Dies bedeutet, dass alle Elemente des Arrays einzeln abgerufen werden. Anschließend wird der angegebene Befehl / die angegebene Operation auf jedes Element angewendet und dann in ein neues Array verschoben.
Adnan Tariq

Antworten:

23

.mapist nur eine Methode, die einen Rückruf akzeptiert, den Rückruf für jedes Element des Arrays aufruft und den Wert einem neuen Array zuweist. Es ist nichts Besonderes daran. Sie können es sogar ganz einfach selbst implementieren:

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]

Um vollständig spec-kompatibel zu sein, dann werden Sie auch benötigen unter anderem zu prüfen, dass das thisein Objekt ist, dass der callbackaufrufbar ist, und auf .callden Rückruf mit dem zweiten Parameter zu übergeben , myMapwenn es ein, aber das sind Details nicht wichtig für ein beginnendes Verständnis von Funktionen höherer Ordnung.

Bestimmte Leistung
quelle
8
Das erinnert mich an einige andere Antworten
Bergi
7

Ich denke, jeder Anbieter sollte es gemäß der Spezifikation implementieren

Die eigentliche Implementierung, zum Beispiel V8, kann etwas komplex sein, beziehen Sie sich zunächst auf diese Antwort . Sie können die v8-Quelle auch in Github referenzieren, aber es ist möglicherweise nicht einfach, nur einen Teil isoliert zu verstehen.

Zitiert aus der obigen Antwort:

V8 Entwickler hier. Wir haben verschiedene Implementierungstechniken für "Builtins": Einige sind in C ++ geschrieben, einige in Torque, einige in CodeStubAssembler und einige direkt in Assembly. In früheren Versionen von V8 wurden einige in JavaScript implementiert. Jede dieser Strategien hat ihre eigenen Stärken (Kompromiss zwischen Codekomplexität, Debugbarkeit, Leistung in verschiedenen Situationen, Binärgröße und Speicherverbrauch). Außerdem gibt es immer den historischen Grund, warum sich Code im Laufe der Zeit weiterentwickelt hat.

ES2015 spec:

  1. Sei O ToObject ( dieser Wert).
  2. ReturnIfAbrupt ( O ).
  3. Sei len ToLength (Get ( O , "length")).
  4. ReturnIfAbrupt ( len ).
  5. Wenn IsCallable ( callbackfn ) false ist, lösen Sie eine TypeError- Ausnahme aus.
  6. Wenn thisArg geliefert wurde, lassen Sie T sein thisArg ; lassen sonst T wird nicht definiert .
  7. Sei A ArraySpeciesCreate ( O , len ).
  8. ReturnIfAbrupt ( A ).
  9. Sei k 0.
  10. Wiederholen, während k < len
    1. Sei Pk ToString ( k ).
    2. Sei kPresent HasProperty ( O , Pk ).
    3. ReturnIfAbrupt ( kPresent ).
    4. Wenn kPresent ist wahr , dann
      1. Sei kValue Get ( O , Pk ).
      2. ReturnIfAbrupt ( kValue ).
      3. Sei mappedValue Call ( callbackfn , T , « kValue , k , O »).
      4. ReturnIfAbrupt ( mappedValue ).
      5. Der Status sei CreateDataPropertyOrThrow ( A , Pk , mappedValue ).
      6. ReturnIfAbrupt ( Status ).
    5. Erhöhen Sie k um 1.
  11. Return A .
Sabithpocker
quelle
2
Ich bin neugierig, die Spezifikationen können <li> list-style-typeweder in Chrome noch in FF kopiert werden. Haben Sie die Zahlen manuell eingegeben oder fehlt mir eine bessere Methode?
Bestimmte Leistung
5
@CertainPerformance lol. Kopieren Sie HTML von der Quelle, HTML in das Markdown-Online-Tool.
Sabithpocker