原型中的对象被继承为参考 [英] object in prototype is inherited as reference

查看:86
本文介绍了原型中的对象被继承为参考的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to inherit new object instance using prototype.

测试用例:

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

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

This means that objects in prototype are not inherited as its copies but instead as its reference.

我知道通常您可以这样做.

I know that normally you can do it like this.

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

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

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

这很好,但是在我看来,这不是一个选择.我真的需要在MyObj函数之外定义objName.

This works fine, but in my case this is not an option. I really need to define objName outside the MyObj function.

我设法解决了这个问题

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

但这不是很漂亮,并且此代码的​​性能更差.

But this is not very pretty and the performance of this code is much worse.

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

Is there any way to solve this more elegantly ?

推荐答案

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

This means that objects in prototype are not inherited as its copies but instead as its reference.

不复制原型上的任何内容-原型继承的整个概念是属性 reference 是原型对象的共享属性.因此,如果您希望每个实例的属性都是独立的,则必须将其显式分配给对象,并为 shadow 原型属性;就像在代码中使用_objName属性一样.

Nothing on the prototype is copied - the whole concept of prototypical inheritance is that properties reference the shared properties of the prototype object. So if you want a property to be individual for each instance, you have to explicitly assign it to the object and shadow the prototype property; just as you're doing it with the _objName property in your code.

但这不是很漂亮,并且此代码的​​性能更差.

But this is not very pretty and the performance of this code is much worse.

如果希望它漂亮,请将其移到构造函数中(或使构造函数查找类似于init方法的东西以进行调用(如果存在),则可以在原型上创建该init方法.

If you want it pretty, move it to the constructor (or make the constructor look for something like an init method to call if exists, then you can create that init method on the prototype.

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

To make performance a little better, you can change the getter function to

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

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

though it still has the function call overhead. For even more elegance, you can use a getter property (not supported in old browsers) that removes itself on the first access:

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

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

Now you can omit the function call parenthesis.

这篇关于原型中的对象被继承为参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆