No, the this
keyword by itself isn't considered mutable state. Consider the following program.
const objOne = {
getTwo: () => 2,
addTwo: function (self, num) {
return num + self.getTwo();
}
}
const objTwo = {
getTwo: () => 3
}
console.log(objOne.addTwo(objOne, 2)); // Returns 4
console.log(objOne.addTwo(objTwo, 2)); // Returns 5 instead of 4
The above program clearly has no mutation. It's exactly the same as your original program except that it uses a formal parameter instead of using the this
keyword.
However, this
is usually used together with mutation in OOP. For example, consider the following class.
class Vec2 {
constructor(x, y) {
this.x = x;
this.y = y;
}
add(that) {
this.x += that.x;
this.y += that.y;
}
}
const v1 = new Vec2(1, 2);
const v2 = new Vec2(3, 4);
v1.add(v2);
console.log(v1); // { x: 4, y: 6 }
Clearly, you can have mutation without using this
too.
const Vec2 = (x, y) => ({ x, y });
const add = (self, that) => {
self.x += that.x;
self.y += that.y;
};
const v1 = Vec2(1, 2);
const v2 = Vec2(3, 4);
add(v1, v2);
console.log(v1); // { x: 4, y: 6 }
So, this
is just a special parameter of sorts. By itself, it isn't mutable. However, you can mutate it just as you can mutate any other parameter.
The bigger problem with the this
keyword, and the new
keyword too, are that they are special cases. Normally, you'd call a function as foo(x, y, z)
, but with this
you'd have to call the function as foo.call(x, y, z)
, and with new
you'd have to call the function as new foo(x, y, z)
.
These special cases make it difficult to reuse higher order functions. For example, normally you can do [1, 2, 3].map(foo)
but what if the call to foo
needs to be prefixed with new
? Then, you'd have to write [1, 2, 3].map((...args) => new foo(...args))
. Similarly, what if foo
needs to be called using .call
? Then, you'd have to write [1, 2, 3].map((...args) => foo.call(...args))
.
Clearly, these special cases are making life more complicated, at least in the case of functional programming. To quote the Zen of Python.
Special cases aren't special enough to break the rules.
TLDR: Avoid using this
and new
when writing programs in a functional style.