Почему функции JS-прототипа определяются отдельно быстрее, чем в словаре?

Это может показаться особенно неясным моментом, однако я пытаюсь улучшить свое обоснование на языке Javascript в целом (более конкретно, его лучшие и наиболее эффективные методы).

Во время тестирования теории в http://jsperf.com/ Я придумал некоторые нечетные результаты:

Предположим, что у нас есть два "идентичных" прототипа, которые определяются следующим образом:

Object1

var Object1 = function() {}

Object1.prototype.defaults = {
    radius: 400,
    up: 1
}

Object1.prototype.centerOffset = function() {
    return this.defaults.radius*this.defaults.up;
}

Object2

var Object2 = function() {}

Object2.prototype = {
    defaults: {
        radius: 400,
        up: 1
    },

    centerOffset: function() {
        return this.defaults.radius*this.defaults.up;
    }
}

Object1 имеет согласованное (если предельное: ~ 3%) преимущество перед Object2 при выполнении следующих простых операций:

var o = new Object1();
var offset = o.centerOffset();

&

var o = new Object2();
var offset = o.centerOffset();

Вы можете запустить тесты самостоятельно здесь. Я использую Chrome 25 на OSX 10.6.8.

Я хотел бы знать следующее:

  • В чем причина этой разницы в производительности?
  • Является ли это показателем эффективности какой-либо лучшей практики в javascript?

Спасибо заранее, ребята.

EDIT: Спасибо за ответы - как уже упоминалось, дальнейшее тестирование с моей стороны, похоже, предполагает, что эта проблема - браузер (или, скорее, Javascript-компилятор). Я тестировал дополнительно в Safari, IE 10 и Firefox. IE 10 и Firefox оба дали результаты настолько близко, чтобы не отличаться. Safari выполнил операции над Object2 несколько быстрее, чем операции над Object1 (в среднем около 2%). Я хотел бы знать, что такое outlier (Other), поскольку разница в производительности в этом случае кажется существенной.

Ответ 1

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

С Object1 вы добавляете атрибут существующей функции прототипа. С Object2 вы заменяете существующий прототип собственным конструктором.

Оба не идентичны.

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

Или, скорее, существующая прототипная функция реализована в машинный код, чтобы сделать ее быстрее, и когда вы назначаете свой собственный объект Object2.prototype, функция прототипа теперь является чистым javascript и, следовательно, медленнее.

Детали не так важны, потому что разные интерпретаторы будут обрабатывать это по-другому, важно понимать, что Object1 и Object2 не совсем идентичны.

Ответ 2

Я думаю, что у него есть кое-что, что вы добавляете прототип в Object1 и перезаписываете его в Object2. Чтобы убедиться, я сделал второй пример производительности: http://jsperf.com/correct-way-to-declare-prototype-functions/2

Там я добавил "Object1.prototype = {}" перед назначением функций. Теперь производительность примерно одинакова между Object1 и Object2 (по крайней мере, в хром).