1

我有一些使用显示模块模式的 javascript,如下所示。它接受一个稍后调用的回调函数。我希望该回调函数能够调用类中定义的函数,但它不起作用。

window.MyClass = function() {
  var self = this,

  start = function (callback) {
    callback(self);
  },

  cancel = function() {
    console.log('Cancel invoked');
  };

  return {
    start: start,
    cancel: cancel
  };
};

var myCallbackFunction = function(instance) {
  instance.cancel(); // Error: instance.cancel is not a function
};

var obj = new window.MyClass();
obj.start(myCallbackFunction);

我可以将这个示例重新设计为 Revealing Prototype Pattern 并且它可以按预期工作,所以我的问题是我可以使用 RMP 来实现这个工作,还是只是这个模式的一个限制?

谢谢,罗杰

4

2 回答 2

4
window.MyClass = function() {
  var self = this;

  this.start = function (callback) {
    callback(self);
  };

  this.cancel = function() {
    console.log('Cancel invoked');
  };

  return {
    start: this.start,
    cancel: this.cancel
  };
};

然后,它既是一个实例方法,又可以通过返回值使用。

但是对于这么简单的事情(例如没有私有变量),我会使用直接原型(“原型模式”)。

顺便说一句,如果你正在阅读这个系列,你应该知道这些并不是真正的标准术语。

他还表示,“虽然 JavaScript 在设计时没有像 C# 或 Java 那样考虑类或面向对象编程的概念,但只需稍加工作即可获得类似的结果。” 事实上,JavaScript 是为面向对象编程而设计的,但它是基于原型的。如您所见,它也足够灵活,可以允许替代方案;在某些情况下,这些替代方案肯定更好。

您甚至不需要 self,因为您的对象保持绑定。

所以:

window.MyClass = function(){};

window.MyClass.prototype = {
    start: function (callback) {
        callback(this);
    },

    cancel: function () {
        console.log('Cancel invoked');
    }
};


var myCallbackFunction = function(instance) {
  instance.cancel();
};

var obj = new window.MyClass();
obj.start(myCallbackFunction);
于 2012-10-11T19:43:05.347 回答
1

永远不要从构造函数返回对象。这是那些奇怪的 JS 怪癖之一。

你没有得到 的实例MyClass,你得到的是一个普通的对象。当构造函数返回一个对象时,该对象将被返回,而不是本应返回的实例。

// good!
function MyClass() {};
new MyClass().constructor // returns: function MyClass() {}
new MyClass().constructor == MyClass // true

// bad!
function MyClass() { return {a:123}; };
new MyClass().constructor // returns: function Object() { [native code] }
new MyClass().constructor == MyClass // false

简而言之,古典风格和暴露模块风格并不能很好地融合在一起。

在您的情况下,分配给 的属性的任何功能this都是您将该功能透露给外部。所以也许你想要这个。

window.MyClass = function() {
  var self = this;

  var start = function (callback) {
    callback(self);
  };

  var cancel = function() {
    somePrivateFn();
    console.log('Cancel invoked');
  };

  var somePrivateFn = function() {
    console.log('private function!');
  };

  this.start = start;
  this.cancel = cancel;
};

但是如果你不需要任何私有的东西(你的例子揭示了一切,所以没有什么是私有的)使用像 Matthew 建议的基于原型的方法,这在所有方面都更快更简单。

于 2012-10-11T19:58:00.160 回答