在JavaScript类中从“私有”方法访问“公共”方法

12

在一个类中,有没有一种方法可以从“私有”函数中调用“公共”JavaScript函数?

请查看下面的类:

function Class()
{
    this.publicMethod = function()
    {
        alert("hello");
    }

    privateMethod = function()
    {
        publicMethod();
    }

    this.test = function()
    {
        privateMethod();
    }
}

这是我运行的代码:

var class = new Class();
class.test();

Firebug报错如下:

publicMethod未定义:[在此错误处中断] publicMethod();

在不访问全局类变量(即class.publicMethod())的情况下,有没有其他方法可以在privateMethod()中调用publicMethod()?


4
希望这只是你示例中的一个笔误,但是你的 privateMethod 是一个全局变量。 - Jimmy
在Firefox中,如果我调用class.privateMethod()会出现错误,而class.publicMethod()却可以正常工作,因此似乎这两个函数之间存在一些差异。 - mon4goos
4个回答

8
您可以在构造函数的作用域中保存一个变量来持有对this的引用。
请注意:在您的例子中,您在privateMethod = function()之前省略了var,使得privateMethod成为全局变量。我已经在这里更新了解决方案。
function Class()
{
  // store this for later.
  var self = this;
  this.publicMethod = function()
  {
    alert("hello");
  }

  var privateMethod = function()
  {
    // call the method on the version we saved in the constructor
    self.publicMethod();
  }

  this.test = function()
  {
    privateMethod();
  }
}

5

被接受的答案可能会产生不良副作用,即在每个实例中都会创建publicMethodtestprivateMethod的单独副本。避免这种情况的惯用语是:

function Class()
{}

Class.prototype=(function()
{
    var privateMethod = function(self)
    {
        self.publicMethod();
    }


    return 
    {
        publicMethod: function()
        {
            alert("hello");
        },
        test: function()
        {
            privateMethod(this);
        }
    };
}());

换句话说,你需要将 this 作为参数传递给私有函数。作为回报,你会得到一个true原型,而不必让每个实例都带有自己版本的私有和公共函数。

2
不错!你也可以使用 privateMethod.call(this) 而不是传入。 - gnarf

2

torazaburo的答案是最好的,因为它避免了多次创建私有成员的副本。我很惊讶Crockford完全没有提到它。或者,根据您喜欢声明公共成员函数的语法,您可以这样做:

function Class()
{}

(function() {
    var privateMethod = function(self) {
        self.publicMethod();
    };

    Class.prototype.publicMethod = function() {
        alert('hello');
    };

    Class.prototype.test = function() {
        privateMethod(this);
    };
}());

0

这种方法不可取吗?虽然我不太确定

var klass = function(){
  var privateMethod = function(){
    this.publicMethod1();
  }.bind(this);

  this.publicMethod1 = function(){
    console.log("public method called through private method");
  }

  this.publicMethod2 = function(){
    privateMethod();
  }
}

var klassObj = new klass();
klassObj.publicMethod2();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接