Почему функции 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 (по крайней мере, в хром).