如何正确判断js中this的指向?

2019-07-091972次阅读javascript

如果用一句话说明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

 

上一篇: new的实现原理是什么?  下一篇: javascript深拷贝和浅拷贝的区别是什么?实现一个javascript深拷贝  

如何正确判断js中this的指向?相关文章