Method Chaining in JavaScript


3 minute read


Are you still a JavaScript padawan learner? Then this post is for you. Maybe you’re still going over the basics of JavaScript, learning how to define functions, how objects work, and some of the other baby steps. And maybe you’ve toyed around with that semi-well known library for querying the DOM (and for doing wayyyy too many other things, IMO), le jQuery. If you have or if you’ve tried out another library, you’ve likely seen something like this:

myLib.doSomething().thenDoSomethingElse();

Or you might have learned about method chaining for something like array transformation:

anArray
    .filter((element) => element === "foobar")
    .map((element) => element.aProperty);

If you haven’t seen this or are writing all your method invocations out on separate lines, it’s time to consider method-chaining. It can sometimes make your code much more easy to read. Consider: This:

const aModule = require('something');

const.doMethod();
const.doAnotherMethod();
const.doYetAnotherMethod();
const.reallyWeAreCallingSomethingElse();
const.done();

…could be this!

const aModule = require('something');

// these operations are meaningfully grouped
const.doMethod().doAnotherMethod().doYetAnotherMethod();
// ... some other operations ...

aModule.reallyWeAreCallingSomethingElse().done();

// ++readability!

##Considerations First, there’s the small bit of extra space your files will take up. This isn’ the primary gain you get, but it’s still something. Remember that you shouldn’t be optimizing first, whether it’s in terms of file size or performance or other considerations. During (good) refactoring is the time and place where you can focus on getting rid of cruft and slimming things down.

The more important gain realized by using method chaining is readability and lowered mental load. Even though reading const four times isn’t a huge mental drain, it’s unnecessary. You can easily omit those repetitions. You need to consider that it’s not just these few lines you or someone else is likely to read, but thousands of other lines of code. And if every single file duplicates code, you’re going to be wasting mental energy.

Now, a caveat: there are plenty of times when an intermediate operation in between method calls means you’ll need to not chain methods together. Not a problem at all! You see, the big idea is to write appropriate and elegant code, so when you really need to separate calls out, do so!

It’s All About This

So, how do you allow your custom objects to use method chaining? It’s all about this. The this binding in JavaScript is provided as the ‘execution context’ for a given function. There are at least four different general ways that this takes on value in JavaScript, but it’s really all about context and the call-site for a function.

So, how do you make the execution context of a method available to the next method call so it can be chained? One general approach is to just return this. That way, you can set up the next method call so it can execute in the same context as it’s predecessor.

const chainModule = (() => {
    const privateValue = "private";

    function privateMethod() {
        console.log("I am a private method");
    }
    return {
        publicValue: "public",
        publicMethod() {
            privateMethod();
            console.log("public method called!");
            return this;
        },
        exposeprivateValue() {
            console.log(privateValue);
            return this;
        },
    };
})();

chainModule.publicMethod().exposeprivateValue();

This isn’t a magical fix for all your code — you need to be extremely wary of accidentally losing your this binding to an implicit global and there are other considerations to be had. But at the very least this should enable you to start writing more fluent APIs in your npm modules and elsewhere!

Happy coding.

Related: