Вопрос о наследовании прототипа в JavaScript - PullRequest
3 голосов
/ 03 марта 2011

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

Вот пример

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

a = new A("brad");

A.prototype = {
  talk: function(){
    return "hello " + this.name;
  }
}

a.talk() // doesn't work
b = new A("john");
b.talk() // works

У меня сложилось впечатление, что a будет искать метод talk() вПрототип A, так что любая модификация прототипа A, до или после создания a, будет отражена, но, похоже, это не так.Может кто-нибудь объяснить это для меня?

Ответы [ 2 ]

4 голосов
/ 03 марта 2011

Это разница между изменением и заменой прототипа.

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

a = new A("brad");
// Change, don't replace.
A.prototype.talk = function(){
    return "hello " + this.name;
};

a.talk() // works
b = new A("john");
b.talk() // works

Вот что происходит:

// Continued from above
var old_proto = A.prototype;

// Nuke that proto
A.prototype = {
talk: function() {
    return "goodbye " + this.name;
}
};

var c = new A("Al");

a.talk() // hello brad
b.talk() // hello john
c.talk() // goodbye Al

old_proto.say_goodbye = function() {
    return "goodbye " + this.name;
};

a.say_goodbye() // goodbye brad
b.say_goodbye() // goodbye john
c.say_goodbye() // TypeError c.say_goodbye is not a function.
3 голосов
/ 03 марта 2011

В поддержку хорошего ответа Шона: нет ничего плохого в замене всего прототипа, если вы делаете это до , то вы создаете экземпляры объекта. Это также работает:

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

A.prototype = {
  talk: function(){
    return "hello " + this.name;
  }
}

a = new A("brad");

a.talk() // works

Только не забудьте заменить его позже (если только это не то, что вы пытаетесь сделать).

В вашем исходном примере A не было вашего пользовательского прототипа во время создания вашего первого экземпляра, но он имел его при создании второго, потому что вы создали прототип между ними.

Цепочка прототипов создается при создании экземпляра объекта, поэтому, как вы продемонстрировали, два экземпляра одного и того же "класса" могут иметь разные прототипы.

Это может вызвать всевозможные проблемы:

var a = new A("brad");
console.log(a instanceof A) // true

A.prototype = {
  talk: function(){
    return "hello " + this.name;
  }
}

console.log(a instanceof A) // false

Объект, на который ссылается a, больше не считается экземпляром A, поскольку instanceof работает, проверяя, находится ли A.prototype в цепочке прототипов a.

...