When using JavaScript to develop, many developers are more or less confused by the point of this, but in fact, about the point of this, remember the most core sentence: which object calls the function, and which object this in the function points to .
Several modes of this:
- In method call mode, this always points to the object where the method is called, and the direction of this is related to the calling position of the method, and has nothing to do with the declaration position of the method (arrow functions are special);
- Under function call, this points to window. When the calling method does not have a clear object, this points to window, such as setTimeout, anonymous functions, etc.;
- In the constructor call mode, this points to the object being constructed;
- In apply, call, bind call mode, this points to the first parameter;
- Arrow function, bind this at the time of declaration, rather than depending on the call location;
- In strict mode, if this is not defined by the execution context, then this is undefined;
Below we give examples and explain the principles for these situations:
1. Method invocation mode
// 声明位置
var test = function(){
console.log(this.x)
}
var x = "2";
var obj = {
x:"1",
fn:test,
}
// 调用位置
obj.fn(); // 1
test(); // 2
In the above code, you can see that this points to the object where it is called, the test method is under the obj object, so this points to obj, and test is under the window object, so this points to window. It can also be seen that this has nothing to do with the position of the declaration, but is related to the position of the call.
But pay attention to the following situation
let obj1={
a:222
};
let obj2={
a:111,
fn:function(){
console.log(this.a);
}
}
obj1.fn = obj2.fn;
obj1.fn(); // 222
This is not difficult to understand. Although obj1.fn is assigned from obj2.fn, the calling function is obj1, so this points to obj1.
2. Function call mode
var a = 1;
function fn1(){
console.log(this.a); // 1
}
fn1();
window.b = 2;
function fn2(){
console.log(this.b); // 2
}
fn2();
//可以理解为 window.fn();
Anonymous function, setTimeout:
(function(){
console.log(this); // window
})();
setTimeout(() => {
console.log(this); // window
}, 0);
setTimeout(function(){
console.log(this); // window
}, 0);
3. Constructor Mode
var flag = undefined;
function Fn(){
flag = this;
}
var obj = new Fn();
console.log(flag === obj); // true
This this points to obj. The internal principle is to use apply to point this to obj. Recall the detailed explanation of the new object process in JavaScript .
4. call、apply、bind
The functions of call and apply are exactly the same, with the only difference: parameters;
the parameters received by call are not fixed. The first parameter is the point of this in the function body, and the second parameter is the following parameters that are passed in sequentially.
apply receives two parameters, the first parameter is also the point of this in the function body. The second parameter is a collection object (array or class array)
var obj = {
name:'111',
getName:function(){
console.log(this.name)
}
};
var otherObj = {
name:'222',
};
var name = '333';
obj.getName(); // 111
obj.getName.call(); // 333
obj.getName.call(otherObj); // 222
obj.getName.apply(); // 333
obj.getName.apply(otherObj); // 222
obj.getName.bind(this)(); // 333
obj.getName.bind(otherObj)();// 222
5. Arrow functions
Regarding the arrow function in ES6, the official explanation is:
the this in the arrow function is the context, and the this in the outer scope is the this in the arrow function.
Judging the this of an arrow function:
Tips: It has no function in the outer layer, this is window; there is a function in the outer layer, depending on who the this of the outer function is and whose this is.
The outer function may be a regular function or an arrow function. Different methods are used to determine the outer this according to the type of function: the
outer function is a regular function, depending on who called the outer function; the
outer function is an arrow function just Say the skills to judge;
let obj={
a:222,
fn:function(){
setTimeout(()=>{
console.log(this.a)});
}
};
obj.fn(); // 222
var name = 'window';
var A = {
name: 'A',
sayHello: () => {
console.log(this.name)
}
}
A.sayHello(); // 输出的是window,根据刚才讲的规则就可以判断
// 那如何改造成永远绑定A呢:
var name = 'window';
var A = {
name: 'A',
sayHello: function(){
var s = () => console.log(this.name)
return s//返回箭头函数s
}
}
var sayHello = A.sayHello();
sayHello();// 输出A
- The call(), apply() and bind() methods are just passing parameters to the arrow function, and have no effect on its this;
- Considering that this is at the lexical level, all rules related to this in strict mode will be ignored (ignoring whether it is in strict mode or not);
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
var obj = {
foo: foo};
console.log(foo.call(obj) === globalObject); // true
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
6. Strict mode
In non-strict mode, this points to the global object window by default;
// 非严格模式
function f1(){
return this;
}
console.log(f1() === window); // true
In strict mode, this is undefined;
// 严格模式
"use strict";
var fn2 = function(){
return this
}
console.log(fn2() == undefined); // true