Simple JavaScript Method Chaining


Method chaining is a way to return an object from a method call that allows for further methods to be called. It’s easier to see than to describe.

Instead of this:

var people = helper.getPeople();
var bob = people.find('bob');
var email = bob.getEmail();

You could do this:

var email = helper.getPeople().find('bob').getEmail();

We get code with fewer variables that’s easier to read.

It does make your code more susceptible to null reference errors but, if you’re happy to deal with that, then this can be a good way to make your code that little bit more intuitive to use.

Return of the Map API

This is the code we wound up with in a previous article:

var mapManager = (function () {
  var map;
 
  // Public
  var createGoogleMap = function (containerId) {
    var options = {
      zoom: 15,
      center: new google.maps.LatLng(-34.397, 150.644),
      mapTypeId: google.maps.MapTypeId.ROADMAP,
    };
 
    map = buildMap(containerId, options);
  };
 
  var move = function (latitude, longitude) {
    var pos = new google.maps.LatLng(latitude, longitude);
    map.setCenter(pos);
  };
 
  // Private
  var buildMap = function (containerId, options) {
    return new google.maps.Map(document.getElementById(containerId), options);
  };
 
  return {
    create: createGoogleMap,
    move: move,
  };
})();

This could be called with:

>mapManager.create("map");
mapManager.move(43.650236593550304, -79.35956954956055);

JSFiddle

At the moment, our public methods don’t return anything. To get method chaining to work, we need to update these methods to return the next object that we want to call. In this case, we’ll be returning a reference to the current object.

What’s this?

In JavaScript this always refers to the “owner” of the function we’re executing, or rather, to the object that a function is a method of.
quirksmode.org

In our library, we’re defining the public functions as objects within the main (anonymous) function. At that point, this references the container function.

So, all we need to do is make sure that our functions return this and we can chain away as much as we want.

Our updated code now looks like this:

var mapManager = (function () {
  var map;
 
  // Public
  var createGoogleMap = function (containerId) {
    var options = {
      zoom: 15,
      center: new google.maps.LatLng(-34.397, 150.644),
      mapTypeId: google.maps.MapTypeId.ROADMAP,
    };
 
    map = buildMap(containerId, options);
    return this;
  };
 
  var move = function (latitude, longitude) {
    var pos = new google.maps.LatLng(latitude, longitude);
    map.setCenter(pos);
    return this;
  };
 
  // Private
  var buildMap = function (containerId, options) {
    return new google.maps.Map(document.getElementById(containerId), options);
  };
 
  return {
    create: createGoogleMap,
    move: move,
  };
})();

and could be called like this:

mapManager.create('map').move(43.650236593550304, -79.35956954956055);

JSFiddle

Easy.