Comment les fonctions d'ordre supérieur, comme .map (), fonctionnent-elles en interne en JavaScript?

17

De nos jours, tout le monde essaie d'utiliser ce type de fonctions d'ordre supérieur pour obtenir des résultats prometteurs en écrivant moins de code. Mais je me demande comment ces fonctions fonctionnent en interne.

Supposons que si j'écris quelque chose comme

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

Je sais que chaque élément du tableau «nombre» itère un par un, mais comment ?

J'ai essayé de le rechercher, mais je n'ai pas encore obtenu de réponse satisfaisante.

Bilal Khan
la source
10
Jetez un oeil sur polyfil d' Array.map
AZ_
C'est une fonction appelée mapqui a été ajoutée au type Array. Cette fonction prend une fonction comme paramètre qui est ensuite appelée lors de la boucle dans le tableau. Les valeurs de retour des appels de fonction sont ensuite renvoyées dans un tableau.
ssc-hrep3
map fonctionne essentiellement comme foreach pour itérer le tableau signifie qu'il obtiendra tous les éléments du tableau un par un, puis appliquera la commande / opération donnée sur chaque élément, puis le poussera dans un nouveau tableau.
Adnan Tariq

Réponses:

23

.mapest juste une méthode qui accepte un rappel, appelle le rappel pour chaque élément du tableau et attribue la valeur à un nouveau tableau. Il n'y a rien de très spécial à ce sujet. Vous pouvez même l'implémenter vous-même assez facilement:

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]

Pour être entièrement conforme aux spécifications, vous devez également vérifier, entre autres, que l' thisobjet est un objet, qu'il callbackpeut être appelé et au .callrappel avec le deuxième paramètre transmis myMaps'il en existe un, mais ce ne sont pas des détails important pour commencer à comprendre les fonctions d'ordre supérieur.

CertainPerformance
la source
8
Cela me rappelle d' autres réponses
Bergi
7

Je suppose que chaque fournisseur est censé l'implémenter selon les spécifications

L'implémentation réelle, par exemple V8 peut être un peu complexe, référez - vous à cette réponse pour commencer. Vous pouvez également référencer la source v8 dans github, mais il peut ne pas être facile de comprendre une seule partie isolément.

Cité de la réponse ci-dessus:

Développeur V8 ici. Nous avons plusieurs techniques d'implémentation différentes pour les "builtins": certaines sont écrites en C ++, certaines en Torque, certaines dans ce que nous appelons CodeStubAssembler, et quelques-unes directement en assembleur. Dans les versions antérieures de V8, certaines étaient implémentées en JavaScript. Chacune de ces stratégies a ses propres forces (compromis sur la complexité du code, le débogage, les performances dans diverses situations, la taille binaire et la consommation de mémoire); De plus, il y a toujours la raison historique pour laquelle le code a évolué au fil du temps.

Spécifications ES2015:

  1. Soit O un ToObject ( cette valeur).
  2. ReturnIfAbrupt ( O ).
  3. Soit len ToLength (Get ( O , "length")).
  4. ReturnIfAbrupt ( len ).
  5. Si IsCallable ( callbackfn ) est faux , lève une exception TypeError .
  6. Si thisArg a été fourni, soit T soit thisArg ; d' autre laisser T être non défini .
  7. Soit A un ArraySpeciesCreate ( O , len ).
  8. ReturnIfAbrupt ( A ).
  9. Soit k 0.
  10. Répéter, tandis que k < len
    1. Soit Pk ToString ( k ).
    2. Soit kPresent une HasProperty ( O , Pk ).
    3. ReturnIfAbrupt ( kPresent ).
    4. Si kPresent est vrai , alors
      1. Soit kValue la valeur Get ( O , Pk ).
      2. ReturnIfAbrupt ( kValue ).
      3. Soit mappedValue être Call ( callbackfn , T , « kValue , k , O »).
      4. ReturnIfAbrupt ( mappedValue ).
      5. Soit le statut CreateDataPropertyOrThrow ( A , Pk , mappedValue ).
      6. ReturnIfAbrupt ( statut ).
    5. Augmentez k de 1.
  11. Retour A .
sabithpocker
la source
2
Je suis curieux, les spécifications <li> list-style-typene sont pas copiables dans Chrome ni FF. Avez-vous écrit les chiffres manuellement ou y a-t-il une meilleure méthode qui me manque?
CertainPerformance
5
@CertainPerformance lol. Copiez HTML de la source, HTML vers l'outil en ligne de démarque.
sabithpocker