具有多个实例的原型上的私有成员

时间:2012-10-27 11:23:55

标签: javascript function scope prototype private-members

这可能吗?

我们确定知道如何在javascript中模拟私人成员:

var Class = (function() {
    var _private;

    Class = function() {
        _private = {};
    };

    Class.prototype.set = function(name, value) {
        _private[name] = value;
    };

    Class.prototype.get = function(name) {
        return _private[name];
    };

    return Class;

})();

这种模式的副作用是当我创建两个实例时:

var instanceOne = new Class();
var instanceTwo = new Class();

然后私人财产在:

之间共享
instanceOne.set('test', 'me');
instanceTwo.get('test');

这个问题有解决方法吗?

此致

1 个答案:

答案 0 :(得分:3)

在JavaScript中使用“私有”成员的标准方法是在构造函数中使用局部变量,并且在调用构造函数的上下文中将任何需要访问它们的内容定义为闭包,如下所示:

function Class() {
    var privateValue = 0;

    this.getPrivateValue = function() {
        return privateValue;
    };
}
Class.prototype.doSomething = function() {
    // This function doesn't have access to `privateValue`
    // except through `getPrivateValue`, even though
    // it's accessible as a member of the instance
};

许多人都对此进行了描述,可能是最着名的Douglas Crockford

请注意,这会引起 Class的每个实例获取getPrivateValue函数的自己的副本的反响,因为每个实例都是一个闭包通过对构造函数的不同调用(这就是它工作的原因)。 (但这并不意味着该功能的所有代码都是重复的;至少有一些引擎 - 谷歌的V8引擎,例如在Chrome和其他地方使用过 - 允许相同的代码由具有不同关联上下文的多个函数对象共享。)

(旁注:我没有使用名称private,因为它是一个保留字。在ES3中,它是ES5中的“未来保留字”;它只是严格模式中的一个; {{3 }}。)

我使用了一个简单的变量而不是一个对象,以避免使事情看起来比它们更复杂。以下是适用于您的示例的方式:

function Class() {
    var privateData = {};

    this.get = function(name) {
        return privateData[name];
    };

    this.set = function(name, value) {
        privateData[name] = value;
    };
}

或者,如果您仍希望跨实例共享类范围的私有数据:

var Class = function() {
    var dataSharedAmongstInstances;

    function Class() {
        var privateDataForEachInstance = {};

        this.get = function(name) {
            return privateDataForEachInstance[name];
        };

        this.set = function(name, value) {
            privateDataForEachInstance[name] = value;
        };
    }

    return Class;
})();