1

到目前为止,我主要从事 Java 项目,我试图了解 Javascript 和模块化。我真的很喜欢 Java 中经常使用的观察者模式,因此我实现了一个 Pub/Sub 模块,它可以用来监听模型模块的变化。

这是我的测试应用程序的组件。

测试模型.js

define("testModel", ["observable"],
  function (observable) {

    var TestModel = (function () {
      function TestModel() {
        this.name = "name";
      }

      TestModel.prototype.setName = function (name) {
        this.name = name;
        this.publish(name);
      };

      observable.makeObservable(TestModel.prototype);
      return TestModel;
    })();

    return {
      TestModel: TestModel
    };
  });

测试视图.js

define("testView", [],
  function () {

    var TestView = (function () {
      function TestView() {
        this.string = "my Name is ";
      }

      TestView.prototype.talk = function (test, self) {
        console.log(self.string + test);
        //HERE this.string IS UNDEFINED !!!!, because TestModel called talk()
        console.log(this.string + test);
      }

      return TestView;
    })();
    return {
      TestView: TestView
    };
  });

testapp.js

define("testapp", ["testModel", "testView"], function (testModel, testView) {

  var initialize = function () {
    var model = new testModel.TestModel();
    var view = new testView.TestView();

    model.addSubscriber(view.talk, view);
    model.setName("Frank");
  }
  return {
    initialize: initialize
  };
});

而 observable 模块只是通过调用向模型添加了 3 个通用函数 makeObservable()

可观察的.js

define("observable", [],
  function () {
    /**
     * Observable Object, holds 3 geneneric functions.
     * @type {{addSubscriber: Function, removeSubscriber: Function, publish: Function}}
     */
    var Observable = {

      addSubscriber: function (callback, subscriber) {
        this.callbacks[this.callbacks.length] = callback;
        this.subscribers[this.subscribers.length] = subscriber;
      },
      removeSubscriber: function (callback) {
        for (var i = 0; i < this.callbacks.length; i++) {
          if (this.callbacks[i] === callback) {
            delete(this.callbacks[i]);
            delete(this.subscribers[i]);
          }
        }
      },
      publish: function (what) {
        for (var i = 0; i < this.callbacks.length; i++) {
          if (typeof this.callbacks[i] === 'function') {
            this.callbacks[i](what, this.subscribers[i]);
          }
        }
      }
    }

    /**
     * Function takes another function Module and adds the 3
     * functions from Observable to it.
     *
     * @param o
     */
    var makeObservable = function (o) {
      // turns an object into a publisher
      for (var i in Observable) {
        o[i] = Observable[i];
        o.callbacks = [];
        o.subscribers = [];
      }
    }

    return {
      makeObservable: makeObservable
    };
  });

现在到我的问题。我真的不想在模型中保存订阅者列表,这在某种程度上违反了松散耦合的原则。但是如果我只TestModel在方法中添加一个回调函数subscribe(),我将无法访问. 因为指向调用了该方法的TestModel。我的解决方法是导致模型中需要订阅者列表。this.stringTestViewthistalk()self

我还尝试在RequireJS 调用和返回TestView的函数中初始化函数之外的 self 变量。TestView但是这个函数只被调用一次,因此这个变量在 Java 中就像一个静态变量,并且在每个TestView.

是否有可能在函数中获取self/this变量talk()来访问字符串,而无需TestModel像现在所做的那样处理它?

4

1 回答 1

0

您可以使用Function.bind创建一个view绑定到其this引用的回调:

model.addSubscriber(view.talk.bind(view));

或者,您可以将订阅者和方法名称传递给Observable(您现在保存订阅者和方法名称而不是订阅者和回调):

model.addSubscriber(view, "talk");

并且Observable将按如下方式调用此方法:

for (var i = 0; i < this.subscribers.length; i++) {
    var sub = this.subscribers[i];
    var methName = this.methodNames[i];
    // invoke the method of sub called methName,
    // and pass sub as the this parameter,
    // and what as the single method parameter.
    sub[methName].call(sub, what);
}
于 2013-10-13T23:09:43.240 回答