是否可以在javascript中调用私有函数内的实例变量?

时间:2013-10-08 00:04:25

标签: javascript

我在javascript中定义了一个充当类的函数。在其中,我定义了几个公共方法,但是有一个私有方法,我需要访问其中的一个公共方法。

function myClass(){ 
   this.myPublicMethod = function(a,b){
       var i = a*b;
       return i;
   }

   function myPrivateMethod(){
        var n = this.myPublicMethod(2,3);
   }
}

这不起作用。有没有办法在myPrivateMethod中访问myPublicMethod?

7 个答案:

答案 0 :(得分:2)

使用this调用私有方法时,您只需指定Function.prototype.call的值。

myPrivateMethod.call(this);

E.g。

function myClass(){ 
   this.myPublicMethod = function(a,b){
       var i = a*b;
       return i;
   }

   function myPrivateMethod(){
        var n = this.myPublicMethod(2,3);
   }

   //calling private method in the *scope* of *this*.
   myPrivateMethod.call(this);
}

请注意,拥有真正的私人成员(不是功能)是以不利用原型为代价的。出于这个原因,我更愿意依赖命名约定或文档来识别私有成员,而不是强制实施真正的隐私。这仅适用于非单件对象。

以下示例演示了上述内容。

//Constructors starts by an upper-case letter by convention
var MyClass = (function () {

    function MyClass(x) {
        this._x = x; //private by convention
    }

    /*We can enforce true privacy for methods since they can be shared
    among all instances. However note that you could also use the same _convention
    and put it on the prototype. Remember that private members can only be 
    tested through a public method and that it cannot be overriden.*/
    function myPrivateMethod() {
        this.myPublicMethod1();
    }

    MyClass.prototype = {
        constructor: MyClass,
        myPublicMethod1: function () {
            //do something with this._x
        },
        myPublicMethod2: function () {
            /*Call the private method by specifying the *this* value.
            If we do not, *this* will be the *global object* when it will execute.*/
            myPrivateMethod.call(this);            
        }
    };

    return MyClass;

})();

答案 1 :(得分:1)

你可以尝试这个来打败当地的范围:

function myClass(){ 

   this.myPublicMethod = function(a,b){
       var i = a*b;
       return i;
   }
   // Capture the original context of `this` myClass
   var self = this;
   function myPrivateMethod(){
        var n = self.myPublicMethod(2,3);
   }
}

我们使用self来维护对原始this的引用,即使上下文正在发生变化(因为我们想在私有方法中调用public方法)。

答案 2 :(得分:1)

执行此操作的一种方法是将每个方法定义为私有,并最终将您想要公开的方法公开(myPrivateMethod即使myPublicMethod被覆盖,也会引用原始myClass.myPublicMethod ):

function myClass(){ 
   var myPublicMethod = function(a,b){
       var i = a*b;
       return i;
   }

   var myPrivateMethod = function (){
        var n = myPublicMethod(2,3);
   }

   this.myPublicMethod = myPublicMethod;
}

答案 3 :(得分:0)

你可以写

var myPublicMethod = this.myPublicMethod = function()...

因此创建了私有和公共实例。

对我来说似乎更干净。

答案 4 :(得分:0)

您可以将公共函数作为参数传递给私有函数,然后调用它。

this.myPublicMethod = function(a,b){
   alert(a * b);
}

function myPrivateMethod(publicMethod){
    var n = publicMethod(2,3);
}
myPrivateMethod(this.myPublicMethod);

这是一个工作小提琴.. http://jsfiddle.net/rxtB2/3/

答案 5 :(得分:0)

调用call的替代方法可以是将方法直接附加到myClass Function对象。

function myClass(){ 

   myClass.myPublicMethod = function(a,b){
       var i = a*b;
       return i;
   }

   this.myPublicMethod = myClass.myPublicMethod;

   function myPrivateMethod(){
        var n = myClass.myPublicMethod(2,3);
        return n;
   }

   console.log("Calling myPrivateMethod()");
   console.log(myPrivateMethod());

}

答案 6 :(得分:0)

如果您只想要“私有”方法,那么您定义它的模式是错误的。我认为可以访问“私有”方法的方法称为特权方法,但可能是错误的。

创建它们的模式如下(在示例中添加了实例变量和继承):

// added to show inheritance
var Parent = function(){
  //instance members
  this.parentInstanceVar=["parent"];
};
var Class = function() {
  //1st step to "inherrit" from Parent
  // take ownership of Parent instance members
  Parent.call(this);
  //to pass all arguments to Parent constructor:
  //Parent.apply(this,arguments);
  //to pass specific agruemtns to Parent
  //Parent.call(this,arg1,arg5);
  this.someIntanceVar=["Class instance"];
};
Class.prototype=(function(parent){
  var ret=(parent&&parent.prototype)?
    Object.create(parent.prototype):
    Object.create({});
  //repair the constructor
  ret.constructor=Class;
  var myPrivateMethod = function() {
    return this.someIntanceVar;
  };
  //privileged method calling "private method"
  ret.myPriviligedMethod=function(){
    return myPrivateMethod.call(this);
  };
  return ret;
}(Parent));//2nd step to "inherit" from Parent
//non privileged method
Class.prototype.nonPrivileged=function(){
  //can't accesss myPrivateMethod here
};

//some tests creating 2 instances
var c1=new Class();
var c2=new Class();
c1.parentInstanceVar.push("added in c1");
c1.someIntanceVar.push("added in c1");
console.log(c2.parentInstanceVar);//=["parent"]
console.log(c2.someIntanceVar);//=["class instance"]
console.log(c1.myPriviligedMethod());//=["Class instance", "added in c1"]
console.log(c2.myPriviligedMethod());//=["Class instance"]
//reason why we repaired the constructor:
console.log((new c1.constructor()) instanceof Class);//=true

此模式仅处理实例共享私有成员。如果您需要特定于实例的私有成员,则不能将原型用于任何特权方法(需要访问“私有”实例特定成员的方法)。你可以使用一个函数来返回一个包含闭包的对象,但我真的不会使用这个模式,因为它忽略了原型及其带来的好处,使得测试变得更加难以克隆。

var createClass=function(privateInstanceVal){
   var privateMethod=function(val){
     privateInstanceVal.push(val);
     return privateInstanceVal;
   };
   return{
     publicInstanceVar:[],
     publicMethod:function(val){return privateMethod(val);}
   }
};
c1=createClass([]);
var b = c1.publicMethod(33);
console.log("b is:",b);
b.push("because I returned the private I made it public");
console.log(c1.publicMethod(0));//=[33, "because ... public", 0]

该示例显示有时通过返回“私有”而将其公开的错误。相反,您可以返回副本:return privateInstanceVal.concat([]);