Потому что так работают прототипы.
В классическом ООП (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
Знаете ли вы, есть ли у этих языков прототипное наследование? – thefourtheye
Это ближайший эквивалент Javascript переменных класса. – user2357112
Эта реализация специфична для J Javascript, но большинство других языков имеют что-то подобное, их обычно называют переменными класса static, но иногда имеют другие имена, такие как «shared» –