五种this的情况
-
在全局环境中简单调用普通函数,严格模式下,函数内的this会被绑定到undefined上,在非严格模式下则会被绑定到全局对象(在浏览器中为window对象,在Node环境中为global对象)。
function f1() { console.log(this); } function f2() { 'use strict' console.log(this); } f1(); // window/global f2(); // undefined 复制代码
函数实际就是一个对象实体,只有在调用时、执行前才能确定它的this是什么,比如下面的情况,函数虽然声明在对象内,但调用是在全局,所以this是全局变量。
let person = { name: "fan", say() { console.log(this); } }; person.say(); // this指向person let sayAlias = person.say; // this指向全局对象 sayAlias(); 复制代码
-
上下文对象(即一个普通对象)调用函数,函数中的this指向该上下文对象。
const student = { name: 'fan', fn: function () { return this; } } console.log(student.fn() === student); // 由于fn是student调用的,所以fn中的this指向student 复制代码
-
通过apply、call、bind改变this的指向。其中apply、call是直接调用,bind只是绑定this为某个对象。
function fn() { console.log(this); } let target = {}; fn.apply(target, ['arg1', 'arg2']); // 输出target fn.call(target, 'arg1', 'arg2'); // 输出target fn.bind(target, 'arg1', 'arg2')(); // 输出target 复制代码
-
构造函数中的this指向。由于new操作符是创建新对象,并绑定至构造函数中的this,然后开始执行构造函数,所以,构造函数中的this指向new操作符创建的新对象。
function Person(name) { this.name = name; console.log(this); } let person = new Person(); // 输出person对象 复制代码
-
箭头函数中的this指向和外层(函数或全局)的this保持一致,并且箭头函数中的this一旦确定,就不能再修改(不能被apply、call、bind和new修改)。
let person1 = { name: "fan" }; function f() { let person2 = { name: "gen" } let sayHello = () => { console.log(this); } sayHello.call(person2); // this仍然为person1 } f1.apply(person1); // 箭头函数的this和外层this保持一致 复制代码
优先级
- 显式绑定:用apply、call、bind、new进行绑定的情况;
- 隐式绑定:根据调用关系决定的绑定。
其中,显式绑定优先级 > 隐式绑定,如下:
let person = {
name: "fan",
say() {
console.log(this);
}
};
let student = {
name: 'gen',
}
person.say.call(student); // this为student,而不是person
复制代码
bind绑定this后,可以被new修改,如下:
function Person(name) {
this.name = name;
}
let target = {
age: 18
};
Person.bind(target); // Person构造函数中的this指向target
let person = new Person(); // new运算符会修改this为person
console.log(target); // target并没有被增加name属性
console.log(person); // person被增加了name属性
复制代码
只要一个函数不是被上下文对象调用、被apply、call、bind、new调用这几种情况,那么无论在哪里调用,该函数的this都指向全局对象。其中要注意若箭头函数是定义在一个对象里,则this指向全局,因为在声明这个外层对象时,对象的this就是全局,箭头函数的this一开始就被绑定并且无法再更改。而如果箭头函数定义在函数内,那么this和该函数的this一样。
let person = {
name: 'fan',
fn: () => {
console.log(this);
}
};
person.fn(); // 输出全局对象
function f1() {
let f2 = () => {
console.log(this);
};
f2();
return f2;
}
let person = {
name: 'fan'
};
f1.call(person)(); // 两次输出person对象
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END