2016-01-26 3 views
0

Я немного смущен механикой прототипирования Javascript. У меня есть следующий код:Свойство прототипа Javascript shadowed

function Person() { 
    this.name = "no name"; 
    this.setName = function (n) { 
    this.name = n; 
    } 
} 

function Student() { 
    this.id = "123"; 
} 
Student.prototype = new Person(); 

s = new Student(); 
s.setName("Klaus"); 

После выполнения кода объект s имеет два имени. Имя «Klaus» в самом объекте и имя «no name» в его прототипе. Я знаю, что свойство затенено и работает отлично, но это не кажется естественным ?! Есть ли лучший способ использовать свойство прототипа?

+2

Почему у Вас есть 'this.setName = функция (п) { this.name = n; } 'const вообще? Почему бы вам не написать 'Person.prototype.setName = function (n) {this.name = n; } 'вне вашей функции' Person() '? –

+0

@Teemu, насколько я понимаю, '.setName' вызывается в контексте' s', хотя это ученик. Таким образом, свойство будет и на 's' (не в прототипе). Изначально при присвоении 'new Person' свойству прототипа' Student' свойство также создается в его прототипе. – nils

+0

Да, но, похоже, OP это понимает, они говорят: «Я знаю, что свойство [prototype] затенено». Однако фактический вопрос неясен. – Teemu

ответ

0

Вы можете напрямую работать с прототипом, но это потребует непропорционального усилия и, вероятно, не считается лучшей практикой. Вместо этого вы можете вызвать конструктор Person в правом this контексте.

Прежде всего, рекомендуется использовать Object.create вместо оператора new при назначении функции функции prototype. С помощью оператора new вызывается конструктор Person, но в неправильном контексте this. Чтобы предотвратить это, вы можете связать их так:

Student.prototype = Object.create(Person.prototype); 

Вместо этого, если вы хотите вызвать конструктор прототипной Link (Person) внутри Student, вы можете call его в конструкторе с правильным this контекстом:

function Student() { 
    Person.call(this); 
    this.id = "123"; 
} 

Кроме того, если вы не хотите, чтобы создать одну функцию для каждого экземпляра, я бы переместить функцию setName к [[Prototype]] из Person:

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

Person.prototype.setName = function (n) { 
    this.name = n; 
} 

function Student() { 
    Person.call(this); // Call the Person constructor 
    this.id = "123"; 
} 
Student.prototype = Object.create(Person.prototype); 

s = new Student(); 
// s.name is 'no name' 
s.setName("Klaus"); 
// s.name is 'Klaus' 

С другой стороны, как уже упоминалось @Teemu, вы можете также поместить name собственность на Person.prototype использовать его в качестве значения по умолчанию:

function Person() { 
} 

Person.prototype.setName = function (n) { 
    this.name = n; 
} 

Person.prototype.name = "no name"; // Define the name directly 

function Student() { 
    Person.call(this); // you only need this, if there are other things happening in the Person constructor that you need as well 
    this.id = "123"; 
} 
Student.prototype = Object.create(Person.prototype); 

s = new Student(); 
// s.name is 'no name' 
s.setName("Klaus"); 
// s.name is 'Klaus' 
+0

Если я делаю это так, 'имя' больше не в прототипе, а в свойстве созданного объекта! Это то, чего я хотел. Это было просто 'Object.create()' вместо 'new'. – landunder

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