我试图理解Javascript原型继承,并且在理解对象实例与其各自的存储原型方法的类的原型属性之间的关系时遇到困难。
我了解到,在类的prototype属性中定义方法允许实例访问/继承这些方法,从而不会重新定义方法。大概是通过允许实例在内存中指向该方法的指针(或与此类似的东西)来实现的。我也理解为什么将方法添加到类的prototype属性中可以使先前创建的实例访问这些“新”方法,因为这些实例只是在访问其prototype属性(包括从其派生的类),从而又可以访问该类的prototype属性。
我不理解的是以下情况:
我用方法定义一个琐碎的对象
function Person(name) {
this.name = name;
}
Person.prototype.greeting = function() {
return "Hello, " + this.name;
}
我创建了一个实例并可以访问数据:
var p = new Person("Ryan");
p.name //"Ryan"
p.greeting() //"Hello, Ryan"
我重新定义人而没有问候:
Person = function (name) {
this.name = name;
}
我仍然可以在前一个实例上使用问候语:
p.greeting() //"Hello, Ryan" but expected error
如果重新定义Person时,它将覆盖内存中先前的Person构造函数,那么,如果不再有任何与Person相关联的方法,那么实例“ p”如何仍可以访问greeting方法?实例是否真的在自己的原型字段中复制了继承类的方法的位置?如果是这样的话,为什么总是有一个“原型链”,如果实例将这些方法的位置直接存储在它们自己的原型字段中,那么处理器必须“走上去”以找到继承的方法? >
非常感谢您的帮助。如果您错过了一些简单的事情,我深表歉意。
答案 0 :(得分:1)
您正在混淆指向对象和对象本身的名称。使用时:
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)
答案 1 :(得分:0)
我刚刚做了一点测试,看来变量p仍在记住先前的对象。
Person = function(name) {
this.name = name;
}
const s = new Person('hello');
s.name; //hello
s.greeting(); //s.greeting is not a function