What Is Method Chaining, and How Does It Work?

This lesson and quiz: https://www.freecodecamp.org/learn/full-stack-developer/lecture-working-with-higher-order-functions-and-callbacks/what-is-method-chaining-and-how-does-it-work

In the lesson it says:

Each method returns a new string, which becomes the target of the next method call.”

Then the quiz question:

In the context of method chaining, what should a method typically return to allow further chaining?

Doesn’t accept the answer “A new object.” with the feedback

“Incorrect. Think about what allows the next method in the chain to be called immediately after the current one.”

Wouldn’t " The object itself (this)." refer to the original object, which would be unmodified?

EDIT: (A further nitpick but I’m not sure this has been introduced yet, but is introduced much later in “Classes”? It’s not mentioned at all in this lesson.)

Well, the transcript does say:

Method chaining is a programming technique that allows you to call multiple methods on the same object in a single line of code.

And this concept is reinforced in the example that chains filter(), map(), and reduce() to a transactions array (the same object).

But I so agree that the question is convoluted because it expects an understanding of this when it was never introduced in the context of chaining and, like you say, isn’t even presented in the context of class properties until much later.

The context for the second question, is in the third question. That is what is meant by “what should a method typically return”.

But yes, in the context of immutable array methods, it would be a copy that is returned. But then, not all array methods are immutable, which is why we now have to versions of them, e.g. toSorted.

I do agree, this concept isn’t explained at all in the video, so it seems a bit of an odd question to ask.

I think it’s meant that each method is called in turn on the results of the previous process. If they were each called on the original array, it would reset each time and wouldn’t be chained.

const totalCreditWithBonus = transactions
  .filter((transaction) => transaction.type === "credit")
  .map((transaction) => transaction.amount * 1.1)
  .reduce((sum, amount) => sum + amount, 0);

filter returns a new object, a filtered version of the original object, which then has map() called on it.

map() returns a new array which then has reduce called on it.

From MDN:

Return value
A new array with each element being the result of the callback function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

reduce also returns a single value which doesn’t really have anything to do with the original object.

I’m not able to find any documentation or empirical evidence that says chained methods return the object itself this ? Or even what is meant by the object itself this other then the original object either unmodified or maybe modified.

sort() does modify and return the original object. This seems like the only method this might be true for?

Thanks that does shed a bit more light… is this how chained functions work internally? Do they typically return this ?

It seems like this is not how filter, map and reduce work? They all seem to return a new object.

Here it says reduce returns the accumulator value:
https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.reduce

  1. Return accumulator.

Which is a new object, not this.
EDIT: But maybe this is implemented as this.accumulator ? But can this be shown somehow? EDIT AGAIN: even then accumulator is not the object itself.

filter and map both create and return new arrays:

https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.filter

https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.map

Only question 3 of the quiz seems to support this answer?

In the context of method chaining,

Even this is a little curious. Do the methods behave any differently when they are chained vs. if they are used standalone?

that depends if the method is mutating or not. if the method is mutating and it returns the original array (example, sort), then it is still the original array but mutated

arr.sort().map() works because sort returns the original array, which has been mutated anyway.

then there are methods that mutate but return a different data type (push, shift, pop)

and there are methods that give back a changed copy (toSorted, map, filter)


no, you need to consider what is returned by the method to know if you can chain on it. For example, join is used on an array and returns a string, so you can chain string methods, while split is used on a string and returns an array so you can chain array methods.

I am not convinced by the question, method chaining does not have the constraint given by that question and answer

I would say the method needs to return a result in order to be chained. All of these methods return the result of the process whether it’s this, a new object or value.

Contrast with forEach() which returns undefined and so you cannot chain a method after it.

Even the example in question 3, getValue() does not return the this object but it does return a value that could be chained.

I think this is the spirit of this question, in the context of chaining, a method can’t return null or undefined. It doesn’t mention this in the lesson but I think it’s an intuitive point.

If I were to reword this question maybe it would be:

In the context of method chaining, what should a method not return to allow further chaining?

undefined or null
The object itself (this).
A new object.
A single value.

Does that work better?

I would say so, but at the same time, some type of values don’t have methods to chain, or they have only toString(), consider numbers, for example, or booleans.

there isn’t a way to return a different number of values, I don’t think this can go as correct answer

You mean something like reduce() would not allow further methods to be chained after?

The methods in question 3 of the quiz are all mutative, like sort(), correct?

let obj = {
    value: 1,
    increment: function() {
        this.value++;
        return this;
    },
    double: function() {
        this.value *= 2;
        return this;
    },
    getValue: function() {
        return this.value;
    }
};

It makes sense that mutative methods can return this but is that not true for non-mutative methods?

I haven’t found a great reference for this yet but it’s talked about here:

JavaScript this keyword refers to the current object in which it is called. Thus, when a method returns this , it simply returns an instance of the object in which it is returned. Since the returned value is an instance of an object, it is, therefore, possible to call another method of an object to the returned value, which is its instance. This makes method chaining possible in JavaScript.

https://www.geeksforgeeks.org/method-chaining-in-javascript/

I find this pretty difficult to understand but it kind of makes sense… but is it true for both mutative methods like sort() and non-mutative methods like filter() ?

As far as I can tell filter(), for example, does not return this or any kind of reference to the original object, but a totally new array

constructs a new array of all the values for which callback returns true.

https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.filter

And yet you CAN chain after filter()

Maybe a totally different question is better?

it depends by what is returned, if it returns a data type on which some methods can be used, than one of those methods can be chained

getValue doesn’t mutate, also it doesn’t return this, it returns a number, so you can’t chain incrememnt or double to it as they are not number methods, they are methods on this/obj only

they returns arrays, which are instances of the Array object, even if sort returns the same array, and fiter returns a new array, so you can chain any array method after them

So this really doesn’t have anything to do with chaining. It’s just whether or not a method returns an object which has methods that you can use for further chaining.

if it’s a method of a class, then yes, returning this is important, like in the obj you wrote earlier, but more generally, with built-in methods, it’s not important, also because you do not see the implementation and don’t know what they do with this anyway

how it is dealt with here seems more an approach for OOP than general method chaining

evil laugh: bwahahaha

Yes, this makes a lot more sense now!

This point also very relevant here, I think.

I like the explanation here:
https://lual.dev/blog/js-method-chaining/

It covers both the general approach:

(<instance>).<method>()
The parenthesis surrounding <instance> don’t change anything at all, and as long as the expression declared inside those parens returns an instance with the right type, we can write anything we want inside it and the code will work.

and OOP approach:

Every single method in the class returns the instance and as a result of this we can append to the chain other methods from the Operation type

and both seem valid.

Maybe everything in JavaScript is put into an object wrapper and they are in some way returning this, but as you mentioned, we don’t really see the specific implementation?

once you are sure you grasp the topics, please open those issues for feedback, please

1 Like