重写对象的构造函数的原型不起作用

时间:2013-07-30 16:09:33

标签: javascript prototype

这是我的代码:

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方法

为什么重写不起作用?我怎么能让它发挥作用?

以下是demo

4 个答案:

答案 0 :(得分:1)

当您分配新的原型对象时,只有新实例化的对象才会拥有新的原型:

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();

这是因为在实例化对象时,会从构造函数的原型中复制对原型对象的引用。如果要添加到所有现有实例和future实例的原型,只需修改原型对象,而不是将全新对象分配给构造函数:

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();

答案 1 :(得分:1)

您成功更改了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.prototypeinstance.__proto__仍指向同一个对象,但对象本身现在还有一个属性。

答案 2 :(得分:0)

我确实添加了这个功能。但是您正在更改prototype对象本身,而不是更改其属性:

Demo

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指向所有新创建的对象的位置,但不会更改已存在的对象。

答案 3 :(得分:0)

虽然这是一种非标准方法,但这对您有所帮助 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();