1

私は今まで主にJavaプロジェクトに取り組んでおり、Javascriptとモジュール化について頭を悩ませようとしています。私は Java で頻繁に使用される Observer パターンが本当に好きなので、モデル モジュールの変更をリッスンするために使用できる Pub/Sub モジュールを実装しました。

テスト アプリケーションのコンポーネントは次のとおりです。

TestModel.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
    };
  });

TestView.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
  };
});

そして、呼び出してモデルに3つの汎用関数を追加するだけの監視可能なモジュール makeObservable()

observable.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、関数の外部で自己変数を初期化しようとしました。TestViewただし、この関数は 1 回しか呼び出されないため、変数は Java の静的変数のように機能し、 のすべてのインスタンスで一意ではありませんTestView

self関数で/this変数を取得してtalk()、文字列を処理せずに文字列にアクセスする可能性はありTestModelますか?

4

1 に答える 1

0

参照にバインドされFunction.bindたコールバックを作成するために使用できます。viewthis

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 に答える