There are two types of functions in JavaScript with respect to this
: arrow functions and non-arrow functions.
function () {}
For non-arrow functions, you can think of this
as just another parameter. Where a typical parameter would be set by passing an argument:
function foo(x) {
return x;
}
foo(1); // returns 1
the this
parameter is set by how the function is called:
function foo() {
return this;
}
var obj = { foo: foo };
foo(); // returns undefined, because it’s not one of the following
// special forms
obj.foo(); // returns obj, because the function was called with dot notation
obj['foo'](); // returns obj, because bracket notation and dot notation
// work the same
foo.call(1); // returns 1, because a function’s `call` method
// sets `this` explicitly
new foo(); // returns a new object of type `foo`‽ read up!
Every non-arrow function has this implicit parameter called this
. The top scope, outside any function, also has a this
. It can be a few different things, depending on your environment; you can safely ignore it.
() => {}
Arrow functions don’t have the implicit this
parameter. They use the this
from their containing scope, like any other variable. In other words, in complete opposition to non-arrow functions, how they’re called doesn’t matter at all; it’s about where the () => { … }
is located.
// `this` outside `foo`…
const foo = () => {
// is the same as `this` inside `foo`. always.
return this;
};
Now, tying it all together, your arrow functions are in the top scope, outside of any other function. That means they have whatever this
was in the top scope. If that isn’t undefined
, you can set values on it, like you’re doing with this.x = 5;
in an arrow function. It’s the same this
every time, though, and it’s certainly not referring to “the function object”.
As for the first example: declaring variables, like with let x = 5;
, has nothing to do with this
at all.