访问原型函数中的私有成员

时间:2015-02-08 23:01:58

标签: javascript

向这样的原型添加新函数时,您无法访问构造函数中定义的变量,因为它们超出了范围。

function Thing() {
    var something = 357;
}

Thing.prototype.doSomething = function () {
    // no access to something because it is out of scope
    console.log(something);
};

感谢在构造函数中将函数添加到原型时的闭包,它可以访问那里定义的变量。

function Thing() {
    var something = 357;

    Thing.prototype.doSomething = function () {
        console.log(something);
    };
}

这是一种可以访问这些变量的好方法,还是有更好的模式来实现相同的目标?我有什么陷阱需要注意吗?

2 个答案:

答案 0 :(得分:2)

您无法从原型中访问私有变量。但是,您可以访问公共变量。我发现这是一个很好的权衡:

function Thing() {
    this._something = 357;
}

Thing.prototype.doSomething = function () {
    console.log(this._something);
};

在属性之前放置_的命名约定只是将其标记为私有的非正式方式,即使它实际上并非如此。

答案 1 :(得分:1)

你的设计存在一些致命缺陷:

  • 每次调用构造函数时都会重新定义原型函数。
  • 所有实例都将共享相同的变量。

每次调用构造函数时重新定义函数都是不可避免的特权函数,但是如果选择沿着那条路走下去,你可以直接在this而不是原型上定义函数。

function SomeObject() {
    var privateVar = 'private value';

    this.somePriviledgedFunction = function () {
        //Use privateVar here
    };
} 

现在,在WeakMap的支持下,有一个新模式可以让您从原型上定义的函数访问私有成员。您基本上会在声明周围使用IIFE,并且只有在该范围内可见的共享WeakMap才能容纳所有私有成员。对象实例将用作键,以便在对象不再存在时,它们的值会被垃圾收集。

var SomeObject = (function (privates) {

    function SomeObject(someValue) {
        privates.set(this, {}); //initialze the privates scope
        privates.get(this).privateVar = someValue;
    }

   Object.defineProperty(SomeObject.prototype, 'privateVar', {
       get: function () {
           return privates.get(this).privateVar;
       }
   });

  return SomeObject;

})(new WeakMap());

var o1 = new SomeObject('first object');
var o2 = new SomeObject('second object');

o1.privateVar; //first object
o2.privateVar; //second object

但请注意,每个需要访问私有变量的SomeObject原型函数都必须在同一个模块中定义(在周围的IIFE中)。另一个问题是,如果一个人不注意设计,而不是来自IIFE之外定义的任何功能,那么其​​他类的实例可能会偷走其他人的私人,这对我来说不是一个真正的问题。