前言
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)