Как функции высшего порядка, такие как .map (), работают внутри JavaScript? - PullRequest
17 голосов
/ 13 января 2020

Каждый в наше время пытается использовать такие функции высшего порядка , чтобы получить многообещающий результат с меньшим количеством кода. Но мне интересно, как эти функции работают внутри.

Предположим, если я напишу что-то вроде

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

Я знаю, что каждый элемент массива 'number' повторяется один за другим, но как ?

Я пытался найти за это, но я не получил никакого удовлетворительного ответа.

Ответы [ 2 ]

23 голосов
/ 13 января 2020

.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]

Чтобы быть полностью совместимым с c, вам также потребуется , чтобы проверить, среди прочего, что this является возразить, что callback может быть вызвано, и .call обратный вызов со вторым параметром, переданный в myMap, если таковой имеется, но это детали, не важные для начального понимания функций высшего порядка.

7 голосов
/ 13 января 2020

Я предполагаю, что каждый поставщик должен реализовать его в соответствии с spe c

Фактическая реализация, например V8, может быть немного сложной, см. этот ответ для начала. Вы также можете ссылаться на источник v8 в github, но может быть нелегко понять только одну отдельную часть.

Цитируемый выше ответ:

Разработчик V8 здесь. У нас есть несколько различных методов реализации для «встроенных»: некоторые написаны на C ++, некоторые в Torque, некоторые в том, что мы называем CodeStubAssembler, а некоторые непосредственно в сборке. В более ранних версиях V8 некоторые были реализованы в JavaScript. Каждая из этих стратегий имеет свои сильные стороны (компромисс между сложностью кода, возможностью отладки, производительностью в различных ситуациях, размером двоичного кода и потреблением памяти); Кроме того, всегда существует историческая причина, по которой код развивался с течением времени.

ES2015 spe c:

  1. Пусть O будет ToObject ( это значение).
  2. ReturnIfAbrupt ( O ).
  3. Пусть len будет ToLength (Get ( O *) 1031 *, "length")).
  4. ReturnIfAbrupt ( len ).
  5. Если IsCallable ( callbackfn ) равен false , выбросить TypeError исключение.
  6. Если было предоставлено thisArg , пусть T будет thisArg ; иначе пусть T будет не определено .
  7. Пусть A будет ArraySpeciesCreate ( O , len ).
  8. ReturnIfAbrupt ( A ).
  9. Пусть k равно 0.
  10. Повтор, а k <<em> len
    1. Let Pk будет ToString ( k ).
    2. Let kPresent be HasProperty ( O , Pk ).
    3. ReturnIfAbrupt ( kPresent ).
    4. Если kPresent is true , затем
      1. Let kValue be Get ( O , Pk ).
      2. ReturnIfAbrupt ( kValue ).
      3. Пусть mappedValue будет Call ( callbackfn , T , « kValue» , k , O »).
      4. ReturnIfAbrupt ( mappedValue ).
      5. Let status be CreateDataPropertyOrThrow ( A , Pk , mappedValue ).
      6. ReturnIfAbrupt ( статус ).
    5. Увеличение k на 1.
  11. Возврат A .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...