Come funzionano internamente le funzioni di ordine superiore, come .map (), in JavaScript?


17

Oggi tutti cercano di utilizzare questo tipo di funzioni di ordine superiore per ottenere risultati promettenti scrivendo meno codice. Ma mi chiedo come funzionino queste funzioni internamente.

Supponiamo che scrivo qualcosa del genere

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

So che ogni elemento dell'array 'number' sta ripetendo uno per uno, ma come ?

Ho provato a cercarlo, ma non ho ancora ricevuto una risposta soddisfacente.


10
Dai un'occhiata al polyfil di Array.map
AZ_

È una funzione chiamata mapche è stata aggiunta al tipo Array. Questa funzione accetta una funzione come parametro che viene quindi chiamata durante il ciclo attraverso l'array. I valori di ritorno delle chiamate di funzione vengono quindi restituiti in un array.
ssc-hrep3

mappa funziona fondamentalmente come foreach per iterare l'array significa che otterrà tutti gli elementi dell'array uno per uno e quindi applicherà il comando / operazione dato su ciascun elemento e quindi lo inserirà nel nuovo array.
Adnan Tariq,

Risposte:


23

.mapè solo un metodo che accetta un callback, invoca il callback per ogni elemento dell'array e assegna il valore a un nuovo array. Non c'è niente di molto speciale al riguardo. Puoi persino implementarlo da solo abbastanza facilmente:

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]

Per essere pienamente conforme alle specifiche, dovresti anche verificare, tra le altre cose, che thissia un oggetto, che callbacksia richiamabile e che .callil callback con il secondo parametro passi myMapse ce n'è uno, ma quelli sono dettagli non importante per una comprensione iniziale delle funzioni di ordine superiore.


8
Questo mi ricorda alcune altre risposte ...
Bergi,

7

Immagino che ogni fornitore dovrebbe implementarlo secondo le specifiche

L'implementazione effettiva, ad esempio V8 può essere un po 'complessa, fare riferimento a questa risposta per iniziare. Puoi anche fare riferimento alla fonte v8 in github ma potrebbe non essere facile capire solo una parte in isolamento.

Citato dalla risposta sopra:

Sviluppatore V8 qui. Abbiamo diverse tecniche di implementazione per i "builtin": alcuni sono scritti in C ++, alcuni in Torque, alcuni in quello che chiamiamo CodeStubAssembler e alcuni direttamente in assembly. Nelle versioni precedenti di V8, alcune erano implementate in JavaScript. Ognuna di queste strategie ha i suoi punti di forza (scambio di complessità del codice, debuggabilità, prestazioni in varie situazioni, dimensioni binarie e consumo di memoria); inoltre c'è sempre la ragione storica per cui il codice si è evoluto nel tempo.

Specifiche ES2015:

  1. Let O be ToObject ( questo valore).
  2. ReturnIfAbrupt ( O ).
  3. Lascia che len sia ToLength (Get ( O , "length")).
  4. ReturnIfAbrupt ( len ).
  5. Se IsCallable ( callbackfn ) è falso , genera un'eccezione TypeError .
  6. Se thisArg è stato fornito, lasciate T essere thisArg ; altrimenti lascia che T non sia definito .
  7. Let A be ArraySpeciesCreate ( O , len ).
  8. ReturnIfAbrupt ( A ).
  9. Lascia che k sia 0.
  10. Ripeti, mentre k < len
    1. Lascia che Pk sia ToString ( k ).
    2. Lascia che kPresent sia HasProperty ( O , Pk ).
    3. ReturnIfAbrupt ( kPresent ).
    4. Se kPresent è vero , allora
      1. Lascia che kValue sia Get ( O , Pk ).
      2. ReturnIfAbrupt ( kValue ).
      3. Lascia che mappedValue sia Call ( callbackfn , T , « kValue , k , O »).
      4. ReturnIfAbrupt ( mappedValue ).
      5. Lascia che lo stato sia CreateDataPropertyOrThrow ( A , Pk , mappedValue ).
      6. ReturnIfAbrupt ( status ).
    5. Aumenta k di 1.
  11. Ritorno A .

2
Sono curioso, le specifiche <li> list-style-typenon possono essere copiate in Chrome né in FF. Hai scritto i numeri manualmente o c'è un metodo migliore che mi manca?
CertainPerformance

5
@CertainPerformance lol. Copia HTML dallo strumento HTML a markdown online.
sabithpocker
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.