You can think of this
as an implicit, immutable, value accompanying a function call.
There are a number of ways it can be set, the most common being that a call of the form o.f()
sets this
to o
within f
. Of course, this
can also be set with call
and apply
and bind
, and in other ways as well.
this
is not like other function parameters. If were a normal parameter, its value could in theory be changed. Instead, it represents a value, a sort of lexical placeholder for the value of this
. In other words, if I call
f.call(5)
and then write
function f() { console.log(this); }
You can think of the this
as being lexically replaced by the value 5. So if I tried to write
function() { this += 5; }
you can think of this as being the equivalent of
function() { 5 += 5; }
which is obvious nonsense. I cannot replace the value 5 with something else. By the same token, if I said
o = {
f: function() { this = o2; }
};
and then call o.f()
, the function is essentially rewritten as
function() { { f: ... } = o2; }
which is equal nonsense. I cannot re-assign the value of an object.
Since this
is a value, not a parameter, it cannot be assigned to or changed. It is not a valid left-hand-side for an assignment, any more than 42
is. We cannot change the value of the value named 42
. We cannot change the value of the value named this
.
The reason for this is that is the specification. In theory, one can imagine a version of JavaScript where this
was mutable. There is no definitive reason why this should not be possible. After all, no matter where it comes from, within the function it is simply a value. It would be confusing, and could result in unexpected behavior, but there is no reason why it could not work.
The primary reason this is not supported is simply that that is not how the language is defined. If your question is "why is the language defined that way", then that is something for language historians to answer. However, one can imagine good reasons for this, involving intuitive code behavior.
Consider the following code:
o = {
f: function() {
this.doSomething();
this = o2;
this.doSomething();
};
It is going to be extremely hard for normal human beings to understand such code. The same two this.doSomething()
calls do two different things due to the intervening change to this
. This alone is a more than adequate reason to prohibit changing the value of this
. All the more so since there is no logical reason for needing to do this, since I can replace the last two lines with a simple o2.doSomething()
.
Just to be clear, of course when we talk about "changing this
", even if we could do that, which we can't, we couldn't possibly mean somehow changing the outside value this
refers to. We all know that in the following case:
function a(x) { x = 2; }
var y = 1;
a(y);
The change to x
within a()
is purely local, and can't possibly affect y
. The same thing would apply equally to this
of course.
One more note on objects wrapping primitives. We know we can write
o5 = Object(5);
to get an object wrapping the number 5. Now I can define a method on this object, as in
o5.f = function() { console.log(this); };
and calling o5.f()
will log
Number {[[PrimitiveValue]]: 5}
So since this object "is" a number, certainly in this case I should be able to say
o5.f = function() { this++; };
But no. this
is not the number 5; it's an object wrapping 5. Those are two very different things. The function above is essentially equivalent to saying
o5.f = function() { Object(5)++; }
which yields
Uncaught ReferenceError: Invalid left-hand side expression in postfix operation
Now I can do arithmetic on the object, such as Object(5) + 1
, because JS will coerce the object to its underlying primitive before adding one. But I cannot re-assign to this object any more than any other. And I cannot modify the primitive number underlying the object. Once the wrapper object is created, the primitive value underlying it is locked in forever.
So the answer to your question is "no, there is no way to change this
". Which is not to say there are not other ways to do other things to accomplish whatever it is you want to accomplish.