Understanding the this
Keyword in JavaScript: Arrow Functions
You might know how this works in regular functions, it refers to the object that directly calls the function, but how does it behave in arrow functions?
In an arrow function, the this
object refers to the object in the scope where the function is defined, rather than the object in the scope where it is invoked.
var name = 'window'; // Actually, window.name = 'window'
var A = {
name: 'A',
sayHello: function() {
console.log(this.name);
}
};
A.sayHello(); // Outputs: A
var B = {
name: 'B'
};
A.sayHello.call(B); // Outputs: B
A.sayHello.call(); // If no parameters are passed, it points to the global window object,
// so it outputs window.name, which is 'window'.
In this case, sayHello
is defined within object A
. Using call
, we change its context to B
, which shows how this
is determined by the calling object.
var name = 'window';
var A = {
name: 'A',
sayHello: () => {
console.log(this.name);
}
};
A.sayHello(); // You might think it outputs A? Wrong! It actually outputs: window
Here, you might expect it to output A
, but it outputs window
instead. This is because the arrow function is defined in the outer scope, which points to the window
object.
The key point here is that "the object in the scope where the function is defined" applies.
The arrow function sayHello
is defined in the outermost JavaScript environment, which points to the window object. Therefore, this
refers to the window object.
In simple terms:
-
If an arrow function is wrapped inside a regular function, then the this of the arrow function will point to the this of the outer function.
-
If there is no wrapping regular function, the this of the arrow function will point to the outermost scope, which is the global object (in browsers, this is window, and in strict mode, it is undefined).
Why do I get "undefined" when I run this in Node.js?
This occurs because, in this context, the
sayHello
function is bound tothis
, which does not refer toglobalThis
. Since Node.js uses CommonJS by default,this
points to themodule.exports
object, which is initially an empty object. As a result, it lacks the name property.For reference, see NodeJS "this" empty object
var name = 'window';
var A = {
name: 'A',
sayHello: function() {
var s = () => console.log(this.name);
return s; // Returns the arrow function s
}
};
var sayHello = A.sayHello();
sayHello(); // Outputs: A
var B = {
name: 'B'
};
sayHello.call(B); // Still outputs: A
sayHello.call(); // Still outputs: A
Here, s
is an arrow function that correctly points to A
, regardless of how sayHello is called.
Let's analyze based on "the object in the scope where the function is defined":
- **Scope of the Arrow Function **: The scope of
s
is thesayHello
function. - Object the Scope Points To: The object that
A.sayHello
points to is A.
Thus, this
in the arrow function s
refers to A.
For a more precise description, the lexical scope of JS is followed here, and the reference link is below.
Lexical Scope in JavaScript – What Exactly Is Scope in JS?
- Cannot Be Used as Constructor Functions: You cannot use the
new
keyword with arrow functions; doing so will throw an error. - No
arguments
Object: Thearguments
object does not exist within arrow functions. If you need to use it, you can use rest parameters instead. - Cannot Use
yield
: Therefore, arrow functions cannot be used as generator functions. - this is Inflexible: The this value of an arrow function cannot be changed or corrected using bind. It always retains the this value from the surrounding lexical context.