这是我的代码:
function Class() {};
Class.prototype.extend = function () {
var instance = new Class();
instance.constructor.prototype = {
say: function () {
console.log("Hello");
}
}
console.log(instance); //Class {extend: function}
}
Class.extend = function () {
this.prototype.extend();
}
Class.extend();
在extend
方法中,我重写了一个实例的原型instance.constructor.prototype = {..}
,
然而,当我记录实例时,它没有显示say
方法
为什么重写不起作用?我该如何让它发挥作用?
这是的演示
您成功更改了Class.prototype
,但将其更改为完全不同的对象。
instance
有一个对其原型对象的引用,称为instance.__proto__
。创建新的Class
实例时,该实例的__proto__
指向与Class.prototype
相同的对象。
但是,您的更改Class.prototype
指的是。这将影响未来实例的__proto__
,但不会影响任何现有实例。instance.__proto__
仍然指向Class.prototype
曾经引用的旧对象
instance
构建完成后,它最初的样子是这样的:
instance.__proto__ ===> { extend: function } <=== Class.prototype
这就是将Class.prototype
分配给新对象后的样子
instance.__proto__ ===> { extend: function }
{ say: function } <=== Class.prototype
相反,您希望修改Class.prototype
引用的对象:
instance.constructor.prototype.say = function () {
console.log("Hello");
}
这会给你一张这样的最后照片:
instance.__proto__ ===> { extend: function, say: function } <=== Class.prototype
请注意,Class.prototype
和instance.__proto__
仍然指向同一个对象,但对象本身现在具有一个附加属性。
当您分配一个新的原型对象时,只有新实例化的对象才会有新的原型:
function Class() {};
Class.prototype.extend = function () {
var instance = new Class();
instance.constructor.prototype = {
say: function () {
console.log("Hello");
}
}
console.log(instance); //Class {extend: function}
console.log(new Class()); //Class {say: function}
}
Class.extend = function () {
this.prototype.extend();
}
Class.extend();
这是因为对原型对象的引用是在实例化对象时从构造函数的原型中复制的。如果你想添加到所有现有实例和未来实例的原型中,你可以修改原型对象,而不是将一个全新的对象分配给构造函数:
function Class() {};
Class.prototype.extend = function () {
var instance = new Class();
instance.constructor.prototype.say = function () {
console.log("Hello");
}
delete instance.constructor.prototype.extend;
console.log(instance); //Class {say: function}
}
Class.extend = function () {
this.prototype.extend();
}
Class.extend();
虽然这是一种非标准的方法,但它将帮助您JS环境允许您编辑proto内部属性。
function Class() {};
Class.prototype.extend = function () {
var instance = new Class();
instance.__proto__ = instance.constructor.prototype = {
say: function () {
console.log("Hello");
}
}
console.log(instance); //Class {extend: function}
console.log(instance.say)
}
Class.extend = function () {
this.prototype.extend();
}
Class.extend();
我确实添加了这个函数。但您正在更改prototype
对象本身,而不是更改其属性:
演示
Class.prototype.extend = function () {
var instance = new Class();
instance.constructor.prototype.say =
function () {
console.log("Hello");
}
console.log(instance);
// Class {extend: function, say: function}
}
当您尝试访问some_obj.some_field
时,JS引擎本身将首先检查对象自身的属性,然后转到some_obj.prototype
并查找some_field
。
通过指定instance.constructor.prototype = {...}
,可以更改prototype
将指向所有新创建的对象的位置,但不适用于已存在的对象。