继承原型中的私有变量 [英] Private variables in inherited prototypes

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

问题描述

我想我误解了Javascript原型继承是如何工作的。具体来说,原型内部变量似乎在多个不同的子对象之间共享。用代码说明最简单:

I think I have misunderstood how Javascript prototypal inheritance works. Specifically, the prototypes internal variables seem to be shared between multiple different sub-objects. It is easiest to illustrate with code:

var A = function()
{
  var internal = 0;
  this.increment = function()
  {
    return ++internal;
  };
};

var B = function() {};
// inherit from A
B.prototype = new A;

x = new B;
y = new B;

$('#hello').text(x.increment() + " - " + y.increment());​

输出 1 - 2 (在 JSBin ),虽然我完全期望结果是 1 - 1 ,因为我想要两个单独的对象。

This outputs 1 - 2 (test it on JSBin), while I fully expected the result to be 1 - 1, since I wanted two separate objects.

如何确保 A 对象不是<$ c的多个实例之间的共享对象$ c> B ?

更新本文重点介绍了一些问题:

Update: This article highlights some of the issues:


问题是每个方法用于创建私有变量的范围,工作正常,也就是操作中的闭包,如果更改私有变量对于一个对象实例,它正在为所有人进行更改。即它更像是一个私有静态属性,而不是一个实际的私有变量。

The problem is that the scope each approach uses to create a private variable, which works fine, is also the closure, in action, that results in if you change a private variable for one object instance, it is being changed for all. I.e. it’s more like a private static property, than an actual private variable.

所以,如果你想拥有私有的东西,更像是非公共常量,任何一个上述方法很好,但不适用于实际的私有变量。私有变量只适用于JavaScript中的单例对象。

So, if you want to have something private, more like a non-public constant, any of the above approaches is good, but not for actual private variables. Private variables only work really well with singleton objects in JavaScript.

解决方案:根据BGerrissen的回答,改变 B 的声明,原型的保留按预期工作:

Solution: As per BGerrissen's answer, changing the declaration of B and leaving of the prototype works as intended:

var B = function() { A.apply(this, arguments); };


推荐答案

私人成员使用原型继承很棘手。首先,它们不能被继承。您需要在每个单独的构造函数中创建私有成员。您可以通过在子类中应用超级构造函数或创建装饰器来完成此操作。

Private members are tricky using prototypical inheritance. For one, they cannot be inherited. You need to create private members in each individual constructor. You can do this by either applying the super constructor in the subclass or create a decorator.

装饰器示例:

function internalDecorator(obj){
    var internal = 0;
    obj.increment = function(){
        return ++internal;
    }
} 

var A = function(){
    internalDecorator(this);
}
A.prototype = {public:function(){/*etc*/}}

var B = function(){
    internalDecorator(this);
}
B.prototype = new A(); // inherits 'public' but ALSO redundant private member code.

var a = new B(); // has it's own private members
var b = new B(); // has it's own private members

这只是超级构造函数调用的变体,你也可以通过使用调用实际的超级构造函数来实现相同的目的。

This is just a variation of the super constructor call, you can also achieve the same by calling the actual super constructor with .apply()

var B = function(){
    A.apply(this, arguments);
}

现在通过继承应用继承B.prototype = new A() A 调用不必要的构造函数代码。避免这种情况的一种方法是使用Douglas Crockfords beget方法:

Now by applying inheritance through B.prototype = new A() you invoke needless constructor code from A. A way to avoid this is to use Douglas Crockfords beget method:

Object.beget = function(obj){
    var fn = function(){}
    fn.prototype = obj;
    return new fn(); // now only its prototype is cloned.
}

您使用的内容如下:

B.prototype = Object.beget(A.prototype);

当然,你可以完全放弃继承并充分利用装饰器,至少私人成员是需要。

Of course, you can abandon inheritance altogether and make good use of decorators, at least where private members are needed.

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

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