前言

JS中的重中之重,也是在面试中被问得最多的问题,在这里this到底是什么?我也时常疑惑于此,特用此文来整理思路理解并方便日后回顾。


函数的调用

JS(ES5)里面有三种函数调用形式:

func(p1, p2) //等价于func.call(undefined, p1, p2)
obj.child.method(p1, p2) //等价于obj.child.method.call(obj.child, p1, p2)
func.call(context, p1, p2) 

把所有的调用转换成call的形式后,this指的就是call后面的第一个参数。
特别注意,全局定义的函数转换成call的形式后,虽然第一个参数为undefined,但是由于全局定义的函数都是挂载到window/global对象上的,所以this会指向window/global。


this是什么?

看调用并转换

  • 例子1
 function showName(){
     console.log(this); //this是window
 }
showName();//showName.call(undefined)

看调用,showName是全局定义函数,挂载在window对象上,所以this是window。

  • 例子2
var name="hello window!";
function testName () {
    var name="hello this!";
    console.log(this.name);
}
testName();//testName.call(undefined)

为什么log出来的不是"hello this!"而是"hello window!"呢?
同样,testName也是挂载在window上的,所以testName函数在调用时this是window,
所以打出来的自然是window.name,也就是全局变量name的值"hello window!"而不是"hello this!"。

  • 例子3
var obj={
    a:"哈哈哈",
    b:function(){
        var a="嘿嘿嘿";
        console.log(this.a);//"哈哈哈"
    }
};
obj.b();//obj.b.call(obj)

那么以上代码为什么会打出"哈哈哈"呢?
显然,这里的this是指obj,也就是会去找obj.a,所以打出的就是"哈哈哈"啦。


总结

fn()            this=>window/global
obj.fn()        this=>obj
fn.call(xxx)    this=>xxx
fn.apply(xxx)   this=>xxx
fn.bind(xxx)    this=>xxx
new Fn()        this=>新的对象
fn = () =>{}    this=>外面的this

方法:
1.看源码中对应的函数是怎么被 call 的(这是最靠谱的办法)
2.看文档
3.console.log(this)


Caddo
59 声望4 粉丝