Подтвердить что ты не робот

Предполагается, что шаблон конструктора JavaScript crockford действительно быстрее?

Недавно я попытался оптимизировать код для часто создаваемого объекта значения. (Трехмерный вектор, fwiw)

Я попытался преобразовать конструкторную функцию из шаблона анонимного метода factory в обычный конструктор JavaScript.

Это привело к серьезному снижению производительности которое меня удивило, поскольку использование "новых" и обычных конструкторов было очень рекомендовано в моей последний вопрос по теме шаблонов JavaScript/ factory.

Вполне возможно, что мой тест слишком упрощен или просто неправильный, или результат недавней оптимизации производительности, сделанной в хромовом движке JavaScript, или все вышеперечисленное. В любом случае, мне бы очень хотелось узнать, почему мои "оптимизации" привели к снижению производительности - и - самое главное: есть ли очевидная проблема с моим jsperf testrun?

4b9b3361

Ответ 1

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

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

Итак, если, например, у вас был код как это:

function make(p) {
    return {
        parm: p,
        addTwo: function() {return this.parm + 2;},
        double: function() {return this.parm * 2;},
        square: function() {return this.parm * this.parm;}
    };
};

он будет работать медленнее, чем это:

function Make(p) {
    this.parm = p;
}
Make.prototype.addTwo = function() {return this.parm + 2;};
Make.prototype.double = function() {return this.parm * 2;}
Make.prototype.square = function() {return this.parm * this.parm;}

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

Ответ 2

Основные отличия между вашими тестами:

  • {} быстрее, чем new Object, что говорит о том, что new работает медленнее, чем при использовании {}, (То же самое относится к [] и new Array.)

  • Ваши тесты дают разные результаты: результат вашей функции make factory не является объектом make. Построенный make имеет прототип, разделяемый всеми объектами make. Ваш результат вашей функции factory является просто голой Object и имеет один прототип в цепочке прототипов (Object.prototype), тогда как объект "Созданный объект" имеет два (Make.prototype, а затем Object.prototype).

    Я создал вилку вашего теста с помощью функции factory, которая фактически возвращает объект make (вместо этого простой Object), используя нестандартное свойство __proto__, и оно намного медленнее, чем использование конструктора. IE не поддерживает __proto__, но результаты от Firefox и Chrome выглядят довольно окончательно.