2015-11-23 4 views
6

У меня есть функция Person конструктора как и с помощью метода SayHelloСвойство на прототипе переопределяет свойство фактического объекта?

var Person = function(firstName,lastName) { 
    this.lastName = lastName; 
    this.sayHello = function() { 
    return "Hi there " + firstName; 
    } 
}; 

Тогда я определяю другую версию метода SayHello на прототипе Person:

Object.defineProperties(Person.prototype,{ 
    sayHello: { 
    value: function() { 
     return 'Hi there'; 
    }, 
    enumerable: true 
    } 
}); 

Теперь, если я создаю Person экземпляр и вызов sayHello на нем - я замечаю, что он использует версию sayHello, которая определена на прототипе.

var JoeBlow = new Person('Joe','Blow'); 

> JoeBlow.sayHello() 
< "Hi there" // I was expecting "Hi there Joe" 

Это для меня сбивает с толку.

Почему объект JoeBlow не использует свой собственный Реализация sayHello вместо того, чтобы искать sayHello на своем прототипе объекта?

+0

Я не уверен, но вы также пытаетесь получить return 'firstname' вместо' this.firstname'. возможно, вы пропустили 'this.firstname = firstname', и тогда вы сможете получить возврат. Потому что он возвращает 'udefined' с ответом Quentin –

+0

@nAz -' firstname' - это переменная, определенная здесь - '(firstName, lastName)' - и все еще находится в области выражения функции, определенного внутри функции конструктора. Я проверил код в своем ответе, и он возвращает «Привет, Джо». – Quentin

+0

@Quentin yeap, вы правы, возможно, я пропустил что-то, поэтому я его протестировал и был удивлен. Спасибо –

ответ

6

По умолчанию свойствами, определяемыми с помощью defineProperties, являются только.

См MDN

writable
true if and only if the value associated with the property may be changed with an assignment operator.
Defaults to false.

К сожалению, при попытке установить только для чтения свойство в старом стиле JS, он не молча, а не бросать исключение, так что это действительно трудно отлаживать.

Если бы вы запустите в strict mode вы бы получили:

TypeError: Cannot assign to read only property 'sayHello' of [object Object]

Вы можете явно определить свойство быть доступны для записи.

Object.defineProperties(Person.prototype,{ 
    sayHello: { 
    value: function() { 
     return 'Hi there'; 
    }, 
    enumerable: true, 
    writable: true 
    } 
}); 

Тогда this.sayHello = function() { не преминут молча, и вы будете успешно маскировать версию свойства живого на прототипе.

+0

Возможно, я не понимаю вопрос, но как этот ответ объясняет, почему поиск свойств разрешает использовать версию прототипа вместо исходной версии? Как ** записываемый ** влияет на версию на самом объекте (или, скорее, заставляет движок использовать версию прототипа вместо этого) – AmmarCSE

+0

@AmmarCSE - версия прототипа ** - ** оригинальная версия. Заменившаяся версия, которую функция-конструктор пытается переписать, терпит неудачу, потому что свойство читается только. Создание свойства записи позволяет 'this.sayHello = something' успешно присваивать новое значение. – Quentin

+0

Подождите, вы говорите, что 'Person.prototype' является' Person' сам? Я думал, в этом случае это будет «Object» – AmmarCSE

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