2

I've been trying to understand the functional composition techniques of Javascript and I came up with his working code of a toy quasi-MVC to demonstrate my question:

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>

In this code I am passing in a function that binds the "hook" variable and returns a function whose scope retains that binding. This is the crux of my question.

I want to be able to abstract out the "hook" binding, so I can just pass in the "state" binding function to a function that then does the "hook" binding. I haven't figured out how to do it with the late-binding facilities Javascript offers (apply/call this). I can pass around object references to keep state, and get stuff done, but I'm interested in more functional approaches to solving this. So:

a) Is there a way to do what I'm trying to do with basic closures in Javascript, if so how, or

b) If I should use late-binding "this"-based methods, what would be the best approach? I'm assuming this is the tried and true way of generalizing function state in Javascript, but the code I'm writing to do this ends up useless.

1 Answers1

0

I think you just want to put the creation of the closure in your 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);

Creating this closure is just a case of partial application, which could of course be abstracted out in a helper function (to be called like update: partial(updateFunction, _hook)).

You can also use bind as a kind of partial application for the this binding of the function. Suppose you wanted to pass the hook as this, you'd either write

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

or just (equivalently)

update: updateFunction.bind(_hook)
Bergi
  • 630,263
  • 148
  • 957
  • 1,375