【问题标题】:The nuances of closing over in Javascript在 Javascript 中关闭的细微差别
【发布时间】:2015-03-19 11:52:30
【问题描述】:

我一直在尝试理解 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;
}
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

在这段代码中,我传入了一个绑定“钩子”变量的函数,并返回一个其作用域保留该绑定的函数。这是我问题的症结所在。

我希望能够抽象出“钩子”绑定,所以我可以将“状态”绑定函数传递给一个函数,然后执行“钩子”绑定。我还没有弄清楚如何使用 Javascript 提供的后期绑定工具来做到这一点(应用/调用它)。我可以传递对象引用以保持状态并完成工作,但我对解决此问题的更多功能方法感兴趣。所以:

a) 有没有办法用 Javascript 中的基本闭包来做我想做的事情,如果有的话,或者

b) 如果我应该使用基于“this”的后期绑定方法,那么最好的方法是什么?我假设这是在 Javascript 中泛化函数状态的行之有效的方法,但我为此编写的代码最终毫无用处。

【问题讨论】:

  • 万岁!有人不厌其烦地提出了一个中规中矩的问题。
  • 抱歉,您说的是什么“挂起”变量?
  • 对不起!我的意思是钩子。这个例子是从一个在钩子上使用挂起方法的程序中提取的。我把他们弄糊涂了——很快就编辑了。
  • 已编辑以修复该错误命名。

标签: javascript functional-programming closures lexical-closures


【解决方案1】:

我想你只是想把闭包的创建放在你的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);

创建这个闭包只是partial application 的一个例子,当然可以在辅助函数中抽象出来(像update: partial(updateFunction, _hook) 一样调用)。

您也可以使用bind 作为函数的this 绑定的一种部分应用。假设你想将钩子传递为this,你要么写

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

或只是(等效地)

update: updateFunction.bind(_hook)

【讨论】:

    猜你喜欢
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多