Simple JS array `concat` clarification

Viewed 132

I understand how the concat method works, but I had one question about a line in the MDN docs.

It says:

The concat methods does not alter this or any of the arrays provided as arguments but instead returns a shallow copy that contains copies of the same elements combined from the original arrays.


My questions is, how is it possible for it to potentially alter the this? Is it saying that the argument arrays could potentially lose their this but instead it preserves it since it's simply creating a new array?

3 Answers

In the call a.concat(b, c), the function being called is a.concat, the this value is a, and the arguments are b and c. What MDN is saying there is that the array a is not changed by that call – unlike, for example, a.push(x).

const arr = [1, 2, 3];

arr.concat([4, 5]);
console.log(arr.join(', '));
// the “this” array in the call `arr.concat([4, 5])` didn’t change

arr.push(6);
console.log(arr.join(', '));
// the “this” array in the call `arr.push(6)` changed

Some functions mutate the arguments that are passed into it, or mutate their calling context. One example is .sort() - if you take an array someArr and then do const result = someArr.sort(), both the result and the original someArr will be sorted (they will reference the same object).

In contrast, concat does not mutate any of the passed arrays, nor its calling context. One without prior knowledge of JS might think that concat adds items to the array concat is being called on, like the following code does:

Array.prototype.myConcat = function(...arrs) {
  arrs.forEach((arr) => {
    arr.forEach(item => {
      this.push(item);
    });
  });
}

const orig = [1, 2, 3];
const another = [4, 5, 6];
orig.myConcat(another);

console.log(orig);

But this is not how the native concat function works - it creates an entirely new array instead, which is what the documentation there is intending to clarify.

When a function is called as a method of an object (such as an array in this example), this is set to the object the method is called on. I think this is the most important thing to take away from this ...

In other words the documentation is simply saying that the original object on which concat is being invoked would not be mutated since it concat creates a brand new array. So concat is one of the few array functions which do not mutate the this. Array.sort/Array.push as mentioned already do mutate the context on which they are called on.

Functions which do not mutate the context they are called on or their arguments in some cases are preferred since they do not cause any side-effects. They are also called pure functions since with a given input they always produce the same output while producing zero side-effects.

There is an entire sub-set of lodash for example called lodash/fp dedicated on the idea of pure functions and functional programming due to some of those advantages. There is also Ramda etc.

Hope this helps.

Related