如果用一句话说明this的指向,那么即是:谁调用它,this就指向谁。
但是仅通过这句话,我们很多时候并不能准确判断this的指向。因此我们需要借助一些规则去帮助自己,this的指向可以按照以下顺序判断:
全局环境中的this
- 浏览器环境:无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this都指向全局对象window;
- node环境:无论是否在严格模式下,在全局执行环境中(在任何函数体外部),this都是空对象{};
是否是new绑定
如果是new绑定,并且构造函数中没有返回function或者是object,那么this指向这个新对象。如下:
构造函数返回值不是function或object。new Super()返回的是this对象。
function Super(age){
this.age = age;
}
let instance = new Super('26');
console.log(instance.age);//26
构造函数返回值是function或object,new Super()是返回的是Super种返回的对象。
function Super(age){
this.age = age;
let obj = {a:'2'};
return obj;
}
let instance = new Super('hello');
console.log(instance);//{a:'2'}
console.log(instance.age);//undefined
函数是否通过call,apply调用,或者使用了bind绑定,如果是,那么this绑定的就是指定的对象【归结为显式绑定】。
function info(){
console.log(this.age);
}
var person = {
age:20,
info
}
var age = 28;
var info = person.info;
info.call(person);//20
info.apply(person);//20
info.bind(person)();//20
这里同样需要注意一种特殊情况,如果call,apply或者bind传入的第一个参数值是undefined或者null,严格模式下this的值为传入的值null/undefined。非严格模式下,实际应用的默认绑定规则,this指向全局对象(node环境为global,浏览器环境为window)。
function info(){
//node环境中:非严格模式global,严格模式为null
//浏览器环境中:非严格模式window,严格模式为null
console.log(this);
console.log(this.age);
}
var person = {
age:20,
info
}
var age = 28;
var info = person.info;
//严格模式抛出错误;
//非严格模式:node下输出undefined(因为全局的age不会挂在global上);
//非严格模式:浏览器环境下输出28(因为全局的age挂在window上);
info.call(null);
隐式绑定,函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。典型的隐式调用为: xxx.fn()
function info(){
console.log(this.age);
}
var person = {
age:20,
info
}
person.info();//20,执行的是隐式绑定
默认绑定,在不能应用其它绑定规则时使用的默认规则,通常是独立函数调用。
- 非严格模式:node环境中执行全局对象global,浏览器环境中执行全局对象window。
- 严格模式:执行undefined
function info(){
console.log(this.age);
}
var age = 28;
//严格模式:抛出错误,因为this此时是undefined;
//非严格模式:node下输出undefined(因为全局的age不会挂在global上);
//非严格模式:浏览器环境下输出28(因为全局的age挂在window上);
info();
箭头函数的情况:
箭头函数没有自己的this,继承外层上下文绑定的this。
let obj = {
age:20,
info:function(){
return ()=>{
//this继承的是外层上下文绑定的this
console.log(this.age);
}
}
}
let person = {age:28};
let info = obj.info();
info();//20
let info2 = obj.info.call(person);
info2();//28