2015-04-16 2 views
3

У меня есть вопрос о JS прототипирования:Наследование прототипа на основе кода JavaScript отличается от другого?

Если у меня есть следующий конструктор:

function Person(name) { 
    if (!(this instanceof Person)) 
     return new Person(name); 
    this.name = name; 
} 
Person.prototype.sayHello = function() { 
    console.log("Hello from " + this.name); 
} 

Здесь у меня есть метод sayHello связанный с прототипом Человека, который больше памяти эффективным, что это:

function Person(name) { 
    if (!(this instanceof Person)) 
     return new Person(name); 
    this.name = name; 
    this.sayHello = function() { 
     console.log("Hello from " + this.name); 
    } 
} 

Только проблеск:

прототипичный лицо:

enter image description here

Не-прототипичный человек:

enter image description here

Как вы видите, ссылка на sayHelloФункция будет "общий" по всей личности, сотворенной, вместо того, чтобы просто создать новая функция для каждого созданного экземпляра. this затем будет мутировать, чтобы указать правильному человеку, когда он используется внутри контекста sayHello(), когда sayHello() вызывается на , что конкретное лицо.

Теперь другой вариант:

function Person(name) { 
    if (!(this instanceof Person)) 
     return new Person(name); 
    this.name = name; 
    this.__proto__.sayHello = function() { 
     console.log("Hello from " + this.name); 
    } 
} 

И выход такой же, как для Person.prototype.sayHello, а это означает, что sayHello распределяется между различными лицами.

Но есть ли разница между этими двумя подходами? не я думаю, нет, потому что:

Person.prototype === bob.__proto__ // true

Так на самом деле, когда нужно использовать прежний (Person.prototype.* вне функции конструктора) вместо последнего (this.__proto__.* внутри функции конструктора)?

+0

** вероятно, не ответ, просто ссылка цели ** - Вы уже проверили эти хорошие вопросы? 1: http://stackoverflow.com/questions/572897/how-does-javascript-prototype-work?rq=1 - 2: http://stackoverflow.com/questions/2064731/good-example-of-javascripts -prototype-based-inheritance? rq = 1 – briosheje

+4

Всегда! Почему вы хотите каждый раз мутировать прототип *, вызываемый конструктором? Несмотря на то, что метод (ы) все равно будет использоваться совместно, каждый вызов конструктора создает новую версию метода и отбрасывает старый. Просто создайте метод один раз и сделайте с ним. –

+0

@FelixKling Это хорошая причина, но помимо этого нет никаких других различий, верно? – tonix

ответ

2

Развернуть комментарии Felix.

версия, которая гласит:

this.__proto__.sayHello = function() { 
    console.log("Hello from " + this.name); 
} 

не следует использовать.

Каждый раз, когда ограждающий конструктор вызывается код, указанным выше также будет работать, создавая новые копию этой анонимной функции, и перезапись ссылки в настоящее время проводится в prototype.

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

В терминах эффективности использования памяти он очень похож на запись this.sayHello = function(...), потому что ни один из экземпляров фактически не имеет одну и ту же копию функции. В условиях эффективности кода это, возможно, хуже (хотя и эквивалентно использованию Person.prototype.sayHello = ...), потому что для каждого вызова требуется восхождение вверх по цепочке прототипов.