Javascript:从原型方法调用私有方法

时间:2011-12-20 19:00:05

标签: javascript

我确信这一定是一个非常常见的问题但是在对互联网进行了几个小时的搜索之后,我还没有找到答案。这是一个问题:

假设我有一个名为哺乳动物的界面。每个哺乳动物都必须能够入睡和进食。 (将来我可能会抛出Mammal类的异常来强迫孩子们实现这个功能)。

function Mammal() {};

Mammal.prototype.eat = function() {};

Mammal.prototype.sleep = function() {};

现在假设我有一个Dog类来实现Mammal类:

function Dog() {};

Dog.prototype = new Mammal();

Dog.prototype.eat = function() {
    ...
};

Dog.prototype.sleep = function() {
    ... 
};

狗的吃饭功能非常复杂,我想使用辅助功能。我无法弄清楚最好的办法是什么。以下是要点:

  • 永远不应该从狗类的外部调用辅助函数,因此理想情况下它应该是私有的。
  • eat函数无法访问私有函数(原型无法访问私有函数)
  • 我可以将帮助函数放入privalaged函数中,但是:
    • 这仍然是公共功能 - >即:每个人都有权称呼它
    • 它不会是原型的一部分,所以每只狗都需要有自己的辅助功能。如果有很多狗,这似乎效率低下。
  • 我不能使eat函数成为一个私有函数,因为为了使原型继承工作,它需要成为原型的一部分。

问题:如何从原型函数调用私有函数?或者更一般地说:当一个对象(子对象)继承自另一个对象(父对象)时,子方法应该如何使用辅助函数,是否可以将它们设为私有?

3 个答案:

答案 0 :(得分:36)

定义您的Dog"类"在关闭。然后你可以拥有共享的priveliged功能。只要知道在调用它时就必须小心this绑定。

var Dog = (function() {
  function Dog() {};

  // Common shared private function, available only to Dog.
  var privateHelper = function() { ... };

  Dog.prototype = new Mammal();

  Dog.prototype.eat = function() {
    privateHelper()
    // Or this if the helper needs to access the instance.
    // privateHelper.call(this);
    ...
  };

  return Dog;
})();

原型上的函数仍然只是一个函数。因此,遵循与任何其他函数相同的范围和闭包访问规则。因此,如果您定义整个Dog构造函数和原型以及作为自动执行函数的隐蔽范围岛,欢迎您在不暴露或污染公共范围的情况下尽可能多地共享。

这正是CoffeeScript classes编译成JS的原因。

答案 1 :(得分:1)

这是不可能的。如果需要访问私有变量/函数,则必须使用特权(辅助)函数。

有时可以在本地闭包范围中使用辅助函数而不是私有辅助函数(在构造函数范围内),这可以从原型函数访问。请参阅Alex Wayne或Raynos的答案。

你说:

  

我无法使eat函数成为一个私有函数,因为为了使原型继承工作,它需要成为原型的一部分。

为什么不呢?

MammalPrototype = {
    eat: function() {},
    sleep: function() {}
};

function Dog(color) {
    ...
    this.eat = function() {
        ... // using private functions
        MammalPrototype.eat.call(this, options) // ?
    };
};
Dog.prototype = Object.create(MammalPrototype); // inherit from an object
当哺乳动物真的只是一个空函数时,

new Mammal()是可以的。有关其工作原理,请参阅https://stackoverflow.com/a/5199135/1048572。提议的垫片当然不是本机实现的功能,但它正是我们在这里所需要的。不要仅仅为了继承而创建实例!

Dog.prototype.sleep = function() {
    ... 
};

function Dalmatian() {
    Dog.call(this, "black.white");
    ...
}
Dalmatian.prototype = Object.create(Dog.prototype); // sic
Dalmatian.prototype.xyz = function() {};

this上调用超级构造函数意味着接收所有特权方法及其功能。如果您在继承的“类”中使用私有变量和/或函数,则需要执行此操作,否则对继承的特权函数的所有调用将仅影响您将prototype设置为的一个实例。 / p>

答案 2 :(得分:0)

  

当一个对象(子对象)继承自另一个对象(父对象)时,子方法如何使用辅助函数,是否可以使这些私有?

您需要一些抽象层来实现您的目标:Live Example

使用klass

var Mammal = klass(function (privates) {
    privates.local_helper = function () {
        console.log("local_helper invoked"); 
    }

    return {
        constructor: function () {
            console.log("mammal constructed");
            privates(this).caneat = true;
        },
        eat: function () { 
            privates.local_helper();
            console.log("mammal eat");
        },
        sleep: function () { 
            console.log("mammal sleep");
        } 
    }; 
});

var Dog = klass(Mammal, function (privates, $super) {
    return {
        constructor: function () {
            $super.constructor.call(this);
            console.log("dog constructed"); 
        },
        eat: function () {
            $super.eat.call(this);
            privates.local_helper();
            console.log("dog eat");
            console.log(privates(this).caneat);
        }
    };
});

var dog = new Dog();
dog.eat();