我应该如何操作具有相同原型的另一个对象的“私有”成员?

时间:2013-10-09 20:50:41

标签: javascript oop functional-programming

在像Java这样的基于类的语言中,我有时会利用同一类的其他对象可以访问类的私有成员这一事实。例如,

class BitSet {
    private int[] words;

    public void and(BitSet set) {
        for (int i = 0; i < words.length; i++)
            words[i] &= (i < set.words.length) ? set.words[i] : 0; 
    }
}

现在,我正在使用构造函数模式创建JavaScript以创建“私有”成员:

function BitSet() {
    var words = [];

    this.and = function (set) {
        // This is roughly what I'm trying to achieve.
        for (i = 0; i < words.length; i++)
             words[i] &= (i < set.words.length) ? set.words[i] : 0;
    }

    // This would solve the problem,
    // but exposes the implementation of the object and
    // clutters up the API for the user

    this.getWord = function(index) {
        return words[index];
    }
}

我知道我应该以不同的方式处理这个问题(而不是那么面向对象)。有没有人建议更好的模式?

1 个答案:

答案 0 :(得分:1)

JavaScript是一种原型的面向对象编程语言,而不是经典的面向对象编程语言。 JavaScript中没有类,但由于prototype-class isomorphism

,您可以将原型建模为类
function CLASS(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

CLASS函数允许您创建看起来像类的原型。但它们不是课程。与其他语言中的类不同,JavaScript中的原型没有访问说明符。一切都必须是公开的或hidden inside closures

var BitSet = CLASS({
    constructor: function () {
        this.words = [];
    },
    and: function (set) {
        var length = this.words.length, setWords = set.words;
        for (var i = 0; i < length; i++) this.words[i] &= setWords[i] || 0;
    }
});

事实上,JavaScript没有类或访问说明符是一件好事,因为确实不需要它们。想一想。你真的需要像Java这样的语言的访问说明符吗?如果一切都是公开的,它真的会产生如此大的影响吗?在我的拙见中,它不会。

有些人认为将所有内容公开是很糟糕的,因为它暴露了实现细节并且不必要地混淆了用户API。不对。只是不要记录您希望保密的属性。如果用户不需要知道某个属性,那么就不要记录它。

如果出于安全考虑需要将变量设为私有,则JavaScript会有闭包。无论如何,其他对象(即使是同一个类)也不需要访问这些属性。因此,不应该存在这样一种情况:您需要将变量保持为私有并使其可以被其他类对象访问。

最后,公开属性有很多好处:

  1. 由于属性是公共的,因此您无需在构造函数内创建闭包。
  2. 可以在原型上共享方法。因此,所有类的实例共享方法。
  3. 您可以将对象初始化与对象的方法分开。
  4. 代码更具可读性和可维护性。
  5. 对象创建速度更快。