Попытка понять суть прототипов в JavaScript - PullRequest
30 голосов
/ 30 января 2011

Я понимаю, что об этом спрашивали сотни раз, однако я не могу понять концепцию "почему" прототипы в JavaScript правильные, в отличие от имитации классов (да, я знаю, что JavaScript - это язык на основе прототипов)- Я так много собрал).

Как и многие другие люди, стремящиеся сделать JavaScript повседневным языком, который я использую, я привык к обычному стилю ООП-класса, как я играл в Java (и используемые классы в ActionScript, а также PHP).Однако, хотя я думаю Я понимаю, как работают прототипы, я не могу понять, зачем они нужны.

Вот мой пример сценария того, как я в настоящее время понимаю прототипы в JavaScript:

var Apple = function() {
    // An apple?
};

Apple.prototype.color = "red";

Apple.prototype.changeColor = function(new_color) {
    this.color = new_color;
};
Apple.prototype.getColor = function() {
    alert('color: '+this.color);
};

var apple1 = new Apple();
var apple2 = new Apple();
apple2.changeColor("green");
apple1.getColor();
apple2.getColor();

... Я предполагал, что, возможно, прототип имел в виду, что он совместно использует один и тот же объект, вместо того, чтобы просто создавать новый объект каждый раз - однако, очевидно, что это не так, поскольку и apple1, иApple2 по-прежнему имеют разные цвета (после запуска указанного скрипта).

Затем я написал это в виде объектно-ориентированного скрипта:

var Apple = function() {
    this.color = "red";

    this.changeColor = function(new_color) {
        this.color = new_color;
    };
    this.getColor = function() {
        alert('color: '+this.color);
    };
};

var apple1 = new Apple();
var apple2 = new Apple();
apple2.changeColor("green");
apple1.getColor();
apple2.getColor();

С точно такими же результатами (как и ожидалось)).... Почему последний код не рекомендуется?У меня нет проблем с использованием прототипов (при условии, что я использовал их правильно), но мне нужно понять концепцию «почему».

... Любая помощь?

Ответы [ 2 ]

31 голосов
/ 30 января 2011

... Я предполагал, что, возможно, прототип имел в виду, что он разделяет один и тот же объект, а не просто создает новый объект каждый раз ...

Это так. Есть один объект-прототип, который используется всеми экземплярами, созданными из конструктора.

... однако, очевидно, что это не тот случай, так как и apple1, и apple2 имеют разные цвета, все же (после запуска указанного скрипта).

Для определенных типов (например, число, логическое значение, ноль, неопределенное значение или строка), когда вы изменяете свойство, существующее в объекте-прототипе, например, через this.color, оно создает свойство color в экземпляре , Прототип остается неизменным, поэтому для новых экземпляров будет задан цвет по умолчанию, определенный в прототипе.

Если вы обновили элемент массива или объекта, на который ссылается свойство объекта-прототипа, это изменение будет видно во всех экземплярах.

... Почему последний код не рекомендуется?

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


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

var Apple = function() {
      // Here "this" is the object being constructed. As such, we're adding
      //   a property "rotten" to every instance created
    this.rotten = false;
};

   // adding a "color" property to the prototype object
Apple.prototype.color = "red";

   // set the property "color" on the instance to the value of "new_color"
Apple.prototype.changeColor = function(new_color) {
    this.color = new_color;
};
   // first check to see if this instance has its own "color" property. If so,
   //    use it. If not, look at the prototype object to see if it exists.
Apple.prototype.getColor = function() {
    alert('color: '+this.color);
};

// two new instances each have their own "rotten" property, and don't have a
//    "color" property. Both share the prototype object, so if "color" is 
//    requested, it will come from there
var apple1 = new Apple(); 
var apple2 = new Apple();

// This will add an "color" property to the "apple2" instance
apple2.changeColor("green");

// Doesn't have a "color" property, so it looks to the prototype object
apple1.getColor();

// Has a "color" property, so it uses that instead of the "color" on the prototype
apple2.getColor();
6 голосов
/ 30 января 2011
Прототип

позволяет добавлять методы и свойства к классу и применять его не только к классу, но и к любым текущим экземплярам объектов этого класса.

...