原型中的对象作为引用继承

2023-12-14

我想使用原型继承新的对象实例。

测试用例:

var MyObj = function() {}
MyObj.prototype.objName = {} 
// I want this to be a different object for each instance of MyObj

var o1 = new MyObj (),
    o2 = new MyObj ();

o1.objName['a'] = 1;
o2.objName['a'] = 2;

alert(o1.objName['a']) // 2
alert(o1.objName === o2.objName) // true

这意味着原型中的对象不会作为其副本继承,而是作为其引用继承。

我知道通常你可以这样做。

var MyObj = function() {
    this.objName = {}
}

var o1 = new MyObj(),
    o2 = new MyObj();

alert(o1.objName === o2.objName) // false

这工作正常,但就我而言,这不是一个选择。我确实需要在 MyObj 函数之外定义 objName 。

我设法用这个“解决”这个问题

MyObj.prototype.objName = function() {
    if ( this._objName === undefined ) {
        this._objName = {};
    }
    return this._objName;
}

var o1 = new MyObj(),
    o2 = new MyObj();

o1.objName()['a'] = 1;
o2.objName()['a'] = 2;

alert(o1.objName()['a']) // 1

但这不是很漂亮,而且这段代码的性能要差得多。

有什么办法可以更优雅地解决这个问题吗?


这意味着原型中的对象不会作为其副本继承,而是作为其引用继承。

原型上的任何内容都不会被复制 - 原型继承的整个概念是属性参考原型对象的共享属性。因此,如果您希望每个实例都有一个单独的属性,则必须将其显式分配给对象并shadow原型属性;就像你正在做的那样_objName您的代码中的属性。

但这不是很漂亮,而且这段代码的性能要差得多。

如果你想要它漂亮,请将它移动到构造函数(或者让构造函数寻找类似init如果存在要调用的方法,那么您可以在原型上创建该 init 方法。

为了使性能更好一点,您可以将 getter 函数更改为

MyObj.prototype.getObj = function() {
    var obj = {};
    this.getObj = function(){ return obj; }; // overwrite itself
    return obj;
};

尽管它仍然有函数调用开销。为了更加优雅,您可以使用 getter 属性(旧浏览器不支持),该属性在第一次访问时会自行删除:

Object.defineProperty(MyObj.prototype, "objName", {
    get: function() {
        var obj = {};
        Object.defineProperty(this, "objName", {
            value: obj,
            writable: true //?
        });
        return obj;
    },
    enumerable: true,
    configurable: true
});

现在您可以省略函数调用括号。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

原型中的对象作为引用继承 的相关文章

随机推荐