Jak funkcje wyższego rzędu, takie jak .map (), działają wewnętrznie w JavaScript?

17

W dzisiejszych czasach wszyscy starają się korzystać z tego rodzaju funkcji wyższego rzędu, aby uzyskać obiecujące wyniki przy pisaniu mniejszej ilości kodu. Ale zastanawiam się, jak te funkcje działają wewnętrznie.

Załóżmy, że napiszę coś takiego

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

Wiem, że każdy element tablicy „liczba” iteruje się jeden po drugim, ale jak ?

Próbowałem go znaleźć, ale nie uzyskałem jeszcze zadowalającej odpowiedzi.

Bilal Khan
źródło
10
Spójrz na polyfil Array.map
AZ_
Jest to wywołana funkcja, mapktóra została dodana do typu Array. Ta funkcja przyjmuje funkcję jako parametr, który jest następnie wywoływany podczas zapętlania tablicy. Zwracane wartości wywołań funkcji są następnie zwracane w tablicy.
ssc-hrep3
map działa w zasadzie jak foreach dla iteracji tablicy oznacza, że ​​pobierze wszystkie elementy tablicy jeden po drugim, a następnie zastosuje podane polecenie / operację na każdym elemencie, a następnie wrzuci go do nowej tablicy.
Adnan Tariq

Odpowiedzi:

23

.mapjest tylko metodą, która przyjmuje wywołanie zwrotne, wywołuje wywołanie zwrotne dla każdego elementu tablicy i przypisuje wartość do nowej tablicy. Nie ma w tym nic specjalnego. Możesz nawet samodzielnie go wdrożyć:

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]

Aby być w pełni zgodnym ze specyfikacją, należy również sprawdzić, między innymi, czy thisjest to obiekt, że callbackmożna wywoływać, i do .callwywołania zwrotnego z drugim parametrem przekazanym, myMapjeśli taki istnieje, ale nie są to szczegóły ważne dla początkującego zrozumienia funkcji wyższego rzędu.

CertainPerformance
źródło
8
Przypomina mi to kilka innych odpowiedzi
Bergi,
7

Chyba każdy sprzedawca powinien wdrożyć go zgodnie ze specyfikacją

Rzeczywista implementacja, na przykład V8, może być nieco złożona, odszukaj tę odpowiedź na początek. Możesz także odnieść się do źródła v8 w github, ale może nie być łatwo zrozumieć tylko jedną część w izolacji.

Cytat z powyższej odpowiedzi:

Deweloper V8 tutaj. Mamy kilka różnych technik implementacji „wbudowanych”: niektóre są napisane w C ++, niektóre w Torque, niektóre w tym, co nazywamy CodeStubAssembler, a niektóre bezpośrednio w asemblerze. We wcześniejszych wersjach V8 niektóre były implementowane w JavaScript. Każda z tych strategii ma swoje mocne strony (zmniejszanie złożoności kodu, debuggowanie, wydajność w różnych sytuacjach, rozmiar pliku binarnego i zużycie pamięci); a ponadto zawsze istnieje historyczny powód ewolucji kodu.

Specyfikacja ES2015:

  1. Niech O będzie ToObject ( ta wartość).
  2. ReturnIfAbrupt ( O ).
  3. Niech len będzie ToLength (Get ( O , "length")).
  4. ReturnIfAbrupt ( len ).
  5. Jeśli IsCallable ( callbackfn ) ma wartość false , zwróć wyjątek TypeError .
  6. Jeśli thisArg został dostarczony, niech T będzie thisArg ; w przeciwnym razie niech T będzie niezdefiniowany .
  7. Niech A będzie ArraySpeciesCreate ( O , len ).
  8. ReturnIfAbrupt ( A ).
  9. Niech k będzie 0.
  10. Powtórz, gdy k < len
    1. Niech Pk będzie ToString ( k ).
    2. Niech kPresent będzie HasProperty ( O , Pk ).
    3. ReturnIfAbrupt ( kPresent ).
    4. Jeśli kPresent jest prawdziwe , to
      1. Niech kValue będzie Get ( O , Pk ).
      2. ReturnIfAbrupt ( kValue ).
      3. Niech mappedValue będzie Call ( callbackfn , T , « kValue , k , O »).
      4. ReturnIfAbrupt ( mappedValue ).
      5. Niech status ma wartość CreateDataPropertyOrThrow ( A , Pk , mappedValue ).
      6. ReturnIfAbrupt ( status ).
    5. Zwiększ k o 1.
  11. Powrót .
sabithpocker
źródło
2
Jestem ciekawy, że specyfikacji <li> list-style-typenie można skopiować w Chrome ani FF. Czy zapisałeś liczby ręcznie, czy brakuje mi lepszej metody?
CertainPerformance
5
@CertainPerformance lol. Skopiuj HTML ze źródła, HTML do narzędzia online z rabatem.
sabithpocker