2015-03-22 2 views
0

Скажем,Почему прототип позволяет нескольким экземплярам использовать общие переменные?

function Person(name) { 
    this.name = name; 
} 

Person.prototype.share = []; 

Person.prototype.printName = function() { 
    alert(this.name); 
} 

var person1 = new Person('Byron'); 
var person2 = new Person('Frank'); 

person1.share.push(1); 
person2.share.push(2); 
console.log(person2.share); //[1,2] 

В приведенном выше, доля может быть использована во всех случаях. Мне интересно, является ли это специфическим для Javascript? что-нибудь подобное для других языков ООП, таких как C++, C# или Java?

+0

Знаете ли вы, есть ли у этих языков прототипное наследование? – thefourtheye

+0

Это ближайший эквивалент Javascript переменных класса. – user2357112

+1

Эта реализация специфична для J Javascript, но большинство других языков имеют что-то подобное, их обычно называют переменными класса static, но иногда имеют другие имена, такие как «shared» –

ответ

0

Потому что так работают прототипы.

В классическом ООП (Java, C# и т. Д.) Классы - это просто «шаблоны», а наследование просто объединяет «шаблоны» для создаваемых экземпляров. В прототипальном наследовании экземпляр представляет собой объект, чей родительский является живым объектом. Они не просто разделяют определение, они имеют один и тот же живой экземпляр родителя.

Так почему же это работает? Это из-за того, как работают прототипы. Если какое-либо свойство не найдено в экземпляре, движок ищет его в родительском. Если все еще не существует, он выглядит выше в цепочке прототипов, пока не достигнет корневого объекта. Если все еще не существует, двигатель может объявить его undefined (если это поиск свойства) или выбросить ошибку (если вы вызвали метод).

instance -> parent -> parent -> parent -> Object 

Вот как JS «наследует». Это в основном просто ищет предка, у которого есть то, что вы хотите, и действуйте на этом уровне. Вот почему экземпляры Person могут нажать на share, потому что они имеют общий родительский объект.

person1 
     \ 
     > Person.prototype (which has share[]) 
     /
person2 

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

function Person(name) { 
    this.name = name; 
    this.share = []; // Instances will have share, but not shared anymore 
} 

// or 
person1.share = []; // Creates a share for person1 only 
+1

В результате пример OP работает только потому, что 'share' указывает на объект (Array), содержимое которого изменяется его функциями-членами. Если вы измените 'share = ''' и измените значение с помощью '+ =', поведение изменится, потому что при присваивании экземпляр объекта получит собственный член 'share', а поиск прототипа не будет выполняться при следующем доступе (т. Е. 'console.log (person2.share)') –

Смежные вопросы