Ответ 1
Я действительно сравнивал такие вещи, и если память работает, прототипная модель обычно медленнее, чем назначение значений непосредственно объекту. Исключение было бы в случаях, когда экземпляры в основном идентичны, а создание экземпляров происходит гораздо чаще, чем доступ к ресурсам.
Итак, если вы определяете свои объекты следующим образом:
var Class = function() {};
Class.prototype.p1 = 1;
Class.prototype.p2 = 1;
Class.prototype.p3 = 1;
Вы избегаете удара производительности во время создания экземпляра, копируя свойства для каждого объекта. Но. Эта производительность показывает свою голову, когда эти свойства доступны или изменены. И если вам придётся получить доступ к этим свойствам без их модификации, вы получаете хитов производительности при прохождении цепи прототипов каждый раз, когда вы обращаетесь к ним (потому что они никогда не копируются в локальный экземпляр). Но, если у вас есть много свойств и только доступ к небольшой части из них для каждого экземпляра, это, вероятно, идеально.
for (var i = 0; i < 100000; i++) {
var x = new Class();
console.log(x.p1);
// ignore p2-p99. we don't need them right now.
}
На другом конце спектра, если вам нужно многократно перебирать свойства в небольшом количестве экземпляров, вам лучше избегать попадания в цепочку прототипов.
var Class = function() {
this.p1 = 1;
this.p2 = 1;
this.p3 = 1;
}
Каждый экземпляр получает свою собственную копию p1, p2 и p3 во время создания. С цепочкой прототипов не нужно проконсультироваться, когда мы обращаемся к любому из них.
var instances = [
new Class(), new Class(), new Class()
];
for (var i = 0; i < 1000000; i++) {
console.log(instances[i % instances.length].p1);
console.log(instances[i % instances.length].p2);
console.log(instances[i % instances.length].p3);
}
Если у меня будет время позже, я проверю это позже, чтобы проверить. До тех пор все, что я могу вам дать, это теория!
ДОПОЛНЕНИЕ
Для использования прототипа существуют две возможности, не связанные с производительностью.
Один, для относительно статических свойств (подобных функций) он сохраняет память. Большинство приложений не поддаются никаким ограничениям. Но при отключении это проблема для вас, используйте прототип.
Два, прототип позволяет назначать функции и свойства всем существующим экземплярам класса. Чтобы выполнить тот же навык с свойствами уровня экземпляра, вам нужно найти и повторить.
ОРИЕНТИРЫ
Per мои последние тесты, которые я запускал только в последних версиях FF и Chrome для OS X, я использовал следующий синтаксис для однослойного ( не наследуемых):
прототип. *
function Class() {}
Class.prototype.a = 1;
Class.prototype.b = 2;
Class.prototype.c = 3;
это. *
function Class() {
this.a = 1;
this.b = 2;
this.c = 3;
}
Между двумя вышеупомянутыми синтаксисами синтаксис this.*
работает примерно на 10,5% быстрее всего.
Добавив уровень наследования, я использовал следующее:
прототип. *
function Base() {}
Base.prototype.a = 1;
Base.prototype.b = 2;
Base.prototype.c = 3;
function Class() {}
Class.prototype = new Base();
это. *
function Base() {
this.a = 1;
this.b = 2;
this.c = 3;
}
function Class() {
Base.apply(this);
}
И в этом случае я нашел синтаксис prototype.*
примерно на 38,5% быстрее всего. Синтаксис this.*
все еще немного ускорялся между браузерами для доступа к члену; но преимущество не было столь же заметным, как преимущество создания.
Я также сравнивал гибридный подход к наследованию:
function Base() {
this.a = 1;
this.b = 2;
this.c = 3;
}
function Class() {
}
Class.prototype = new Base();
В целом, он работал примерно на 0,5% быстрее, чем синтаксис prototype.*
(возможно, незначительный). Тем не менее, это было интересно примерно на 1% медленнее во время создания экземпляра, но на 2% быстрее во время доступа к члену, чем синтаксис prototype.*
. Опять же, не очень важно, но я не могу не спросить, будут ли эти выигрыши масштабироваться по мере увеличения глубины наследования.
Помните, конечно, что эти тесты не были выполнены в хорошо контролируемой обстановке. Я склонен видеть заметные пробелы в производительности как значимые. Но более низкие проценты вполне могут быть вызваны колебаниями загрузки процессора на моей машине.
Все, что сказал,, я бы посоветовал использовать this.*
в случаях, когда наследование не имеет значения или, в котором доступ членов гораздо более распространен, чем экземпляр класса. И, конечно, если вы не хотите выжать каждую унцию производительности из своего веб-приложения, используйте синтаксис, который будет более интуитивно понятным для вас и вашей команды. Большинство веб-приложений будут принимать более сильные более высокие результаты производительности, чем разница в стилях построения объектов.
Например, изменение цвета фона,
document.body.style.backgroundColor = 'blue';
... примерно на 70% медленнее, чем создание экземпляра худшего исполнителя, который я тестировал.