可以从函数原型访问私有构造函数范围的变量吗?

Sea*_*man 8 javascript constructor closures private prototype-programming

根据我对javascript的理解,原型方法无法访问构造函数范围内的私有变量,

 var Foo = function() {
      var myprivate = 'I am private';    
      this.mypublic = 'I am public';
 }

 Foo.prototype = {
     alertPublic: function() { alert(this.mypublic); } // will work
     alertPrivate: function() { alert(myprivate); } // won't work
 }
Run Code Online (Sandbox Code Playgroud)

这很有道理,但有什么方法可以安全和良好的做法吗?由于使用原型提供了性能优势,因为成员函数只分配了一次,我想实现类似的功能,同时仍然可以访问我的私有变量.我不认为它会使用原型,但是有另一种模式,例如工厂方法或闭包方法吗?就像是,

var fooFactory = function() {
    var _alertPrivate = function(p) { alert(p); } // bulk of the logic goes here
    return function(args) {
         var foo = {}; 
         var myprivate = args.someVar; 
         foo.mypublic = args.someOtherVar; 
         foo.alertPrivate = function() { _alertPrivate(myprivate); };
         return foo; 
    }; 
}

var makeFoo = new fooFactory();
var foo = makeFoo(args); 
Run Code Online (Sandbox Code Playgroud)

我不确定每次创建新的Foo时是否创建了_alertPrivate的新副本,或者是否有任何潜在的性能优势.目的是获得类似于原型的功能(因为它节省了内存),同时仍然能够访问私有变量.

谢谢.

Sea*_*man 4

我想出了以下模式来解决这个问题,至少现在是这样。我需要的是一个特权设置器,以便可以从某些原型函数内部更改私有变量,但不能从其他任何地方更改:

 var Foo = (function() {

    // the bulk of the objects behavior goes here and is created once 
    var functions = {
        update: function(a) {
             a['privateVar'] = "Private variable set from the prototype";
        }
    }; 

    // the objects prototype, also created once
    var proto = {
        Update: function() {
             this.caller('update'); 
        }
    };

    // special function to get private vars into scope
    var hoist = function(accessor) {
        return function(key) {
             return functions[key](accessor()); 
        }
    }

    // the constructor itself
    var foo = function foo() {
        var state = {
            privateVar: "Private variable set in constructor",
            // put more private vars here
        }
        this.caller = hoist(function(){
            return state;
        }); 
    }

    // assign the prototype
    foo.prototype = proto;

    // return the constructor
    return foo; 

 })(); 
Run Code Online (Sandbox Code Playgroud)

基本上,指向对象内部状态的指针通过简单访问器上的闭包提升到其原型。}。在任何给定实例上使用“调用者”函数允许您调用仅创建一次但仍然可以引用该实例中保存的私有状态的函数。同样重要的是要注意,原型之外的任何函数都无法访问特权访问器,因为“调用者”只接受引用回范围内的预定义函数的键。

以下是此方法的一些基准,以了解它与纯原型制作的比较。这些数字表示在循环中创建 80,000 个对象实例(请注意,用于基准测试的对象比上面的对象更复杂,这只是为了简化目的):

铬合金:

仅关闭 - 2172ms

原型设计(上述方式)- 822ms

原型设计(标准方式)- 751ms

火狐浏览器:

仅关闭 - 1528ms

原型设计(上述方式)- 971ms

原型设计(标准方式)- 752ms

正如您所看到的,该方法几乎与普通原型设计一样快,并且绝对比仅使用复制函数和实例的普通闭包更快。