Как экземпляры объекта Javascript сохраняют методы после переопределения родительского класса? - PullRequest
2 голосов
/ 10 июля 2019

Я пытаюсь понять наследование прототипов Javascript, и у меня возникают проблемы с пониманием связи между экземплярами объектов и свойством прототипа их соответствующих классов, в котором хранятся унаследованные методы.

Я понимаю, что определение методов в свойстве прототипа класса позволяет экземплярам получать доступ / наследовать эти методы, чтобы методы не переопределялись. Предположительно это достигается путем предоставления экземпляру указателя на метод в памяти (или что-то очень похожее на это). Я также понимаю, почему добавление методов в свойство prototype класса позволяет ранее созданным экземплярам получать доступ к этим «новым» методам, поскольку экземпляры просто получают доступ к свойству prototype (которое включает в себя класс, из которого они происходят), которое, в свою очередь, обращается к свойству prototype класса.

Что я не понимаю , так это следующий сценарий:

  1. Я определяю тривиальный объект с помощью метода:

    function Person(name) {
      this.name = name;
    }
    Person.prototype.greeting = function() {
      return "Hello, " + this.name;
    }
    
  2. Я создаю экземпляр и могу получить доступ к данным:

    var p = new Person("Ryan");
    p.name //"Ryan"
    p.greeting() //"Hello, Ryan"
    
  3. Я переопределить Персона без приветствие:

    Person = function (name) {
      this.name = name;
    }
    
  4. Я все еще могу использовать приветствие в предыдущем экземпляре:

    p.greeting() //"Hello, Ryan" but expected error

Если при переопределении Person он перезаписывает предыдущий конструктор Person в памяти, как получается, что экземпляр "p" может по-прежнему обращаться к методу приветствия, если больше нет такого метода, связанного с Person? Это тот случай, когда экземпляры фактически копируют расположение методов своих унаследованных классов в собственном поле прототипа? Если это так, то почему всегда говорят о «цепочке прототипов», которую процессор должен «подойти», чтобы найти унаследованные методы, если экземпляр хранит расположение этих методов непосредственно в их собственном поле прототипа?

Помощь очень ценится. Я прошу прощения, если есть что-то простое, что я пропустил.

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Вы смешиваете имена, которые указывают на объекты и сами объекты.Когда вы используете:

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

, вы не переопределяете объект, на который указывает имя Person.Вы просто берете имя Person и указываете на новое - на новую функцию.Старый Person.protoype все еще находится в памяти, и экземпляр p содержит ссылку на него, а p.constructor по-прежнему указывает на исходную функцию Person.

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

function Person(name) {
  this.name = name;
}
Person.prototype.greeting = function() {
  return "Hello, " + this.name;
}
var p = new Person("Ryan");

// p's prototype is Person.prototype
console.log(Object.getPrototypeOf(p) === Person.prototype) // true

// grab a reference of the protoype for later
let Pprotot = Person.prototype

// point variable Person at something else
Person = function (name) {
  this.name = name;
}

// p's prototype is STILL the old Person.prototype
console.log(Object.getPrototypeOf(p) === Pprotot)    // still true

// p also still holds a reference to the old function (through the prototype)
console.log(p.constructor)

// but it's not the same thing the variable Person now points to
console.log(p.constructor === Person)
0 голосов
/ 10 июля 2019

Я только что провел небольшой тест, и похоже, что переменная p все еще помнит предыдущий объект.

Person = function(name) {
  this.name = name;
}
const s = new Person('hello');
s.name; //hello
s.greeting(); //s.greeting is not a function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...