2

私は Javascript の関数合成手法を理解しようとしてきましたが、私の質問を示すためにおもちゃの準 MVC の彼の作業コードを思いつきました:

var modelFactory = function() {
  var _state = false;
  var _listener = null;

  var _updateView = function() {
    _listener(_state);
  };

  var _interface = {
    registerListener: function(listen) {
      _listener = listen;
    },
    eventHandler: function() {
      _state = true;
      _updateView();
    }
  };
  return _interface;
};

var viewFactory = function(updateFunction) {
  var _hook = $('<div class="box"></div>');
  $('body').append(_hook);

  var _interface = {
    getHook: function getHook() {
      return _hook;
    },
    update: updateFunction(_hook)
  };

  return _interface;
};


var main = function() {

  var modelInstance = modelFactory();

  var viewInstance = viewFactory(
    function bindHook (hook) {
      return function bindState (state) {
        if (state === true) {
          hook.addClass("red");
        } else {
          hook.removeClass("red");
        }
      };
    }
  );

  modelInstance.registerListener(viewInstance.update);
  modelInstance.eventHandler(); // When called, mutates _state, then calls the listener
};

$(document).ready(main);
.box {
  background-color: #000;
  width: 100px;
  height: 100px;
}
.red {
  background-color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

このコードでは、「フック」変数をバインドし、スコープがそのバインディングを保持する関数を返す関数を渡しています。これが私の質問の核心です。

「フック」バインディングを抽象化できるようにしたいので、「状態」バインディング関数を「フック」バインディングを行う関数に渡すだけです。Javascript が提供する遅延バインディング機能 (これを適用/呼び出す) を使用してそれを行う方法がわかりません。オブジェクト参照を渡して状態を維持し、作業を完了することができますが、これを解決するためのより機能的なアプローチに興味があります。そう:

a) Javascript の基本的なクロージャーでやろうとしていることを行う方法はありますか?

b) 遅延バインディングの「this」ベースのメソッドを使用する必要がある場合、最善のアプローチは何ですか? これは、Javascript で関数の状態を一般化するための実証済みの正しい方法だと思いますが、これを行うために書いているコードは役に立たなくなります。

4

1 に答える 1

0

クロージャーの作成をあなたのに入れたいだけだと思いますviewFactory

function viewFactory(updateFunction) {
  var _hook = $('<div class="box"></div>');
  return {
    getHook: function getHook() {
      return _hook;
    },
    update: function(state) {
      return updateFunction(_hook, state)
    }
  };
}

…
var viewInstance = viewFactory(function bindState(hook, state) {
  hook[state ? "addClass" : "removeClass"]("red");
});
$('body').append(viewInstance.getHook());
modelInstance.registerListener(viewInstance.update);

このクロージャの作成は、部分適用の 1 つのケースにすぎません。もちろん、ヘルパー関数で抽象化することもできます (のように呼び出されますupdate: partial(updateFunction, _hook))。

関数のバインディングのbind一種の部分適用としても使用できます。thisフックを として渡しthisたい場合、次のように記述します。

update: function(state) {
  return updateFunction.call(_hook, state); // notice the similarity to above
}

または単に(同等に)

update: updateFunction.bind(_hook)
于 2015-01-21T03:43:28.220 に答える