JavaScript私有变量的解决方案?

时间:2014-08-18 22:47:51

标签: javascript private-members

我问这个是因为我认为我找到了解决JavaScript问题的方法,而且我想知道我是否已经离开了基础。我希望在这里提出这个问题是合适的。

我相信你知道,JavaScript没有私有属性。这个问题通常使用两种模式中的一种来解决。

第一种是使用闭包在构造函数内创建特权方法,并使用this关键字将它们绑定到对象。这是used by Douglas Crockford技术。这是一个例子:

function Person(name) {
    function getName() {
        return name;
    }
    this.who = getName;
}

这种模式的问题在于污染全局命名空间存在很大的危险:

var me = Person("Karl"); // Oops! no "new"
me.who(); // TypeError: Cannot read property 'who' of undefined
who(); // "Karl" - "who" is in global namespace!

第二种解决方案是使用module pattern。不是将特权方法绑定到this,而是将其绑定到新对象:

function Person(name) {
    function getName() {
        return name;
    }
    return {
        who: getName
    }
}
var me = Person("Karl"); // No "new," but that's OK
me.who(); // "Karl"
who(); // TypeError: undefined is not a function

该模式的问题是该对象没有Person的原型链。因此,您无法正确检查其类型,也无法使用构造函数的原型扩展对象:

console.log(me instanceof Person); // "false"
Person.prototype.what = function() {
    return this.constructor.name + ": " + this.who();
}
me.what(); // TypeError: undefined is not a function

我找到了解决方法。使用具有Person的原型链的临时构造函数,并返回使用临时构造函数构造的对象:

function Person(name) {
    function getName() {
        return name;
    }
    // Temporary constructor
    function F() {
        this.who = getName;
    }
    F.prototype = Person.prototype;
    return new F();    
}
// Can't pollute the global namespace
var me = Person("Karl");
me.who(); // "Karl"
who(); // TypeError: undefined is not a function

// Proper prototype chain: correct type checking, extensible
console.log(me instanceof Person); // "true"
Person.prototype.what = function() {
    return this.constructor.name + ": " + this.who();
}
me.what(); // "Person: Karl"

我对此解决方案有几个相关的问题:

  1. 这种技术有什么缺点吗?
  2. 虽然模块模式和临时构造函数模式已经存在了一段时间,但我从未见过有人把它们放在一起。这是我以前不知道的模式吗?
  3. 如果2号的答案是“不”,我可以为此疯狂道具吗? :)

1 个答案:

答案 0 :(得分:1)

我的问题没有答案,但建议应该以更简单的方式解决所有问题:

function Person(name) {
    "use strict";
    if (!this) return new Person(name);
    function getName() {
        return name;
    }
    this.who = getName;
}
Person.prototype.what = function() {
    return this.constructor.name + ": " + this.who();
}

"use strict"; compatibility

MDN documentation about function context


适用于所有浏览器的替代方案

function Person(name) {
    if (!(this instanceof Person)) return new Person(name);
    function getName() {
        return name;
    }
    this.who = getName;
}
Person.prototype.what = function() {
    return this.constructor.name + ": " + this.who();
}