Ответ 1
Вот один из способов увидеть разницу:
var circle1 = circle(1);
var circle2 = circle(1);
alert(circle1.area == circle2.area);
Для метода 1 вы увидите false
, а Method2 - в true
. Это потому, что в первом случае вы назначаете новую функцию закрытия каждому созданному объекту, два объекта имеют разные функции area
, хотя оба делают то же самое. Во втором случае объекты имеют один и тот же прототипный объект с его методом area
, этот метод, конечно, одинаковый в обоих случаях.
Обычно метод 2 предпочтительнее по нескольким причинам:
- Создание объекта происходит быстрее, потому что необходимо инициализировать только настраиваемые свойства.
- Вы не теряете память при создании нескольких копий одной и той же вещи.
- Вы можете легко узнать, какие из свойств объекта имеют пользовательские значения, вызывая
Object.hasOwnProperty
.
Есть и некоторые недостатки, которые нужно помнить.
- Вы всегда тратите время на создание прототипа, даже если вы никогда не создавали никаких объектов.
- Доступ к свойствам несколько медленнее, потому что JavaScript-движок должен сначала проверить свойства объекта, а затем свойства объекта-прототипа (современные JavaScript-движки оптимизируют это довольно хорошо).
- Существует общая ловушка падения для размещения объектов или массивов на прототипе, они будут разделяться между всеми объектными экземплярами.
Вот пример распространенной ошибки:
function NumberCollection()
{
}
NumberCollection.prototype = {
numbers: [],
sum: function()
{
var result = 0;
for (var i = 0; i < this.numbers.length; i++)
result += this.numbers[i];
return result;
}
}
var c1 = new NumberCollection();
c1.numbers.push(5);
alert(c1.sum()); // Shows 5
var c2 = new NumberCollection();
c2.numbers.push(6);
alert(c2.sum()); // Oops, shows 11 because c1.numbers and c2.numbers is the same
Правильный подход здесь:
function NumberCollection()
{
this.numbers = [];
}
NumberCollection.prototype = {
numbers: null,
sum: function()
{
var result = 0;
for (var i = 0; i < this.numbers.length; i++)
result += this.numbers[i];
return result;
}
}