Почему собственный массив javascript для метода Each значительно медленнее, чем стандарт для цикла? [Дубликат]

17

При чтении исходного кода для игрового движка Quintus я обнаружил, что они интенсивно используют циклы, а не для native forEach .

Моя первоначальная мысль заключалась в том, что метод native forEach будет немного быстрее, чем стандартный для циклов. Тем не менее, после тестирования моей теории с этих эталонных показателей структуры for loop выглядят значительно быстрее.

После того, как тыкаешься, я не могу понять, что происходит под капотом. Кто-нибудь знает причину огромной разницы?

EDIT: Чтобы быть ясным, я спрашиваю, почему это так. Я не спрашиваю «что быстрее».

    
задан David Granado 03.03.2014 в 20:14
источник
  • Вызов функции включает нетривиальные служебные данные, а .forEach выполняет множество вызовов функций. –  Pointy 03.03.2014 в 20:15
  • Я добавил новую редакцию, которую стоит изучить: var foo=""; var fn = function (x) {foo + = x; }; для (x = 0; x <длина; x ++) {fn (x); } –  Joe Frambach 03.03.2014 в 20:21
  • @Pointy Это странно. Я бы подумал, что двигатель включил бы эти функции, как показано здесь: jsperf.com/canvas-pixelwise-manipulation-performance. Может ли быть что-то здесь, препятствующее встраиванию? –  David Granado 03.03.2014 в 20:22
  • @ Подумай, ах ... ты прав. Я думаю, что у меня есть это сейчас. Inlining - это модификация времени выполнения кода javascript. Поскольку forEach является родным, это не происходит на том же уровне, что и встроенный. –  David Granado 03.03.2014 в 21:01
  • Дубликатная маркировка имеет мало смысла. Связанный вопрос задает вопрос, который быстрее, этот вопрос спрашивает, почему. –  Nit 10.09.2015 в 18:43
Показать остальные комментарии

2 ответа

15

InEach включает в себя множество проверок внутри и не так прямо, как простой цикл.
Подробнее см. ссылку на Javascript для Mozilla :

if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisArg */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
      throw new TypeError();

    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++)
    {
      if (i in t)
        fun.call(thisArg, t[i], i, t);
    }
  };
}
    
ответ дан Nit 03.03.2014 в 20:24
  • Хорошая точка. Однако, поскольку это все родное, я ожидаю, что влияние будет намного меньше, чем разница в производительности в 20 раз. Я думаю, что это может быть какая-то комбинация этого и что-то в этой предотвращающей функции. Я буду копать еще несколько новых перспектив. –  David Granado 03.03.2014 в 20:32
  • @DavidGranado любое обновление по этому вопросу за 2017 год будет оценено по достоинству –  Max Heiber 18.12.2016 в 17:00
0

спасибо за вставку реализации; есть ответ прямо там: fun.call медленнее, чем fun , а тест i in t стоит дорого.

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

    
ответ дан Andras 09.05.2017 в 01:12
  • Код, отправленный @Nit, не является фактической реализацией собственного метода forEach –  Bergi 09.05.2017 в 01:27