1

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

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

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

这行不通。有没有办法在 myPrivateMethod 中访问 myPublicMethod?

4

7 回答 7

2

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

myPrivateMethod.call(this);

例如

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;

})();
于 2013-10-08T00:13:35.943 回答
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(因为我们想在私有方法中调用公共方法)。

于 2013-10-08T00:06:58.147 回答
1

做到这一点的一种方法是首先将每个方法定义为私有,最后将您想要的方法设为公开(即使被覆盖myPrivateMethod,也会引用原始方法):myPublicMethodmyClass.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;
}
于 2013-10-08T00:09:57.697 回答
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([]);

于 2013-10-08T05:10:32.573 回答
0

调用的替代call方法是将方法直接附加到myClassFunction 对象。

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());

}
于 2013-10-08T01:15:15.440 回答
0

你可以写

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

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

对我来说似乎更干净。

于 2013-10-08T00:08:46.860 回答
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/

于 2013-10-08T00:16:15.243 回答