乐趣区

捉摸不透的this到底是什么

前言

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)

退出移动版