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

17

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

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

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

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

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

Билал Хан
источник
10
Посмотрите на polyfil Array.map
AZ_
Это вызываемая функция, mapкоторая была добавлена ​​к типу Array. Эта функция принимает функцию в качестве параметра, который затем вызывается во время цикла по массиву. Возвращаемые значения вызовов функций затем возвращаются в массиве.
ssc-hrep3
map в основном работает как foreach для итерации массива, это означает, что он будет получать все элементы массива один за другим, а затем применять данную команду / операцию к каждому элементу и затем вставлять ее в новый массив.
Аднан Тарик

Ответы:

23

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

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

CertainPerformance
источник
8
Это напоминает мне о некоторых других ответах ...
Берги
7

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

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

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

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

ES2015 spec:

  1. Пусть O будет ToObject ( это значение).
  2. ReturnIfAbrupt ( O ).
  3. Пусть len будет ToLength (Get ( O , "length")).
  4. ReturnIfAbrupt ( len ).
  5. Если IsCallable ( callbackfn ) имеет значение false , бросить исключение TypeError .
  6. Если thisArg был предоставлен, пусть T будет thisArg ; иначе пусть T будет неопределенным .
  7. Пусть A будет ArraySpeciesCreate ( O , len ).
  8. ReturnIfAbrupt ( A ).
  9. Пусть к будет 0.
  10. Повторите, пока к < лен
    1. Пусть Pk будет ToString ( k ).
    2. Пусть kPresent будет HasProperty ( O , Pk ).
    3. ReturnIfAbrupt ( kPresent ).
    4. Если kPresent есть правда , то
      1. Пусть kValue будет Get ( O , Pk ).
      2. ReturnIfAbrupt ( kValue ).
      3. Пусть mappedValue будет Call ( callbackfn , T , « kValue , k , »).
      4. ReturnIfAbrupt ( mappedValue ).
      5. Пусть статус будет CreateDataPropertyOrThrow ( A , Pk , mappedValue ).
      6. ReturnIfAbrupt ( статус ).
    5. Увеличьте k на 1.
  11. Возвращение .
sabithpocker
источник
2
Мне любопытно, спецификации <li> list-style-typeне копируются ни в Chrome, ни в FF. Вы написали цифры вручную, или есть лучший метод, который я пропускаю?
CertainPerformance
5
@CertainPerformance лол. Скопируйте HTML из источника, HTML в онлайн-инструмент уценки.
Сабитпокер