In a recent project, I encountered the problem of using “this” in the arrow function incorrectly. After changing the arrow function to “function()”, the pointing of “this” reached the expected value. It is worth studying about this problem.
In the ES5 era before arrow functions, this pointed to its caller. This refers to the object that called the property or method. It’s a bit like the personal pronoun “I”, which refers to the person who said “I” from their mouth.
A simple example:
// The variable defined with var, this refers to window
SayName () is called this.sayname () is called window.sayname ()
var name = 'window';
var sayName = function(){
return this.name
}
console.log(sayName()) //window
console.log(this.sayName()) //window
console.log(window.sayName()) //window
// the sayName method called with obj, where this refers to the obj that called it
var obj = {
name : 'obj'.sayName : function(){
return this.name
}
}
console.log(obj.sayName()) //obj
Copy the code
Later in the ES6 specification, the arrow function this is bound when it is defined and refers to its parent scope, not to the object that calls it. This reference cannot be changed by call or apply.
The arrow function in the object literal refers to this:
// The variable defined with var, this refers to window
// Although the result is the same as the example above, the timing of this is different. The arrow function is bound when it is defined, and the normal function is only determined when it is called
var name = 'window';
var sayName = () = > {
return this.name; / / this point to the window
};
console.log(sayName()); //window
console.log(this.sayName()); //window
console.log(window.sayName()); //window
// The same sayName method called obj, this refers to the parent scope window
var obj = {
name: 'obj'.sayName: () = > {
return this.name; }};console.log( obj.sayName() ); //window
console.log( obj.sayName() === window.sayName() ); //true
Copy the code
This is the behavior that the arrow function this points to in an object literal. Again, there are differences when called with an object instance.
Look at the following example:
var name = 'window'
function Obj(name){ // The Obj constructor
this.name = name;
this.s1 = function(){
return this.name; // For normal function methods, this refers to Obj
}
this.s2 = () = > {
return this.name; // This refers to Obj, because the constructor Obj(name) forms a level 1 scope
};
}
Obj.prototype.s3 = function(){
return this.name; // The common method on the prototype chain, this refers to the constructor Obj of instance obj1
}
Obj.prototype.s4 = () = > {
return this.name; // An arrow function on the prototype chain. When defined, the parent scope of the arrow function is window
}
// Instantiate the object
const obj1 = new Obj('obj');
console.log(obj1.s1()); //obj
console.log(obj1.s2()); //obj
console.log(obj1.s3()); //obj
console.log(obj1.s4()); //window
Copy the code
- The s2() arrow function is going to find
The parent level when it is defined
Scope, because the constructor Obj is also a function, it forms its own scope. When we define s2()The parent scope becomes the domain in which the constructor Obj resides
- The difference between s4() and s2() is that s4() is mounted to the prototype of the constructor,
When s4() is defined, the parent scope of the arrow function is window
, so calling the method with the instance will print ‘window’
Bottom line: Be careful when using arrow functions in object literals and in constructor prototypes where this is not the expected result.