一、this指向问题
(非箭头函数只看调用形式)
1. 直接调用形式:"test()";
- 直接不带任何引用形式去调用函数,this指向window对象,在严格模式下,是undefined(后文解释)
setTimeout(fn,time);//window
function test(){
setTimeout(function(){
console.log(this);
})
}
test(); //window
2. "xxx.test()";
- 谁调用这个函数,this就绑定在谁身上。
- aaa.bbb.ccc.text(); //指向ccc
3. "test.call(xxx)"/"test.apply(xxx)"/"test.bind()"
- 指定this
4. "new test()"
var a = 1;
function test (a) {
this.a = a;
}
var b = new test(2);
console.log(b.a);//2,this指的是new出来的对象b
5. 箭头函数this
- 普通函数只有在调用的时候才会确定该函数内this的指向。
- 箭头函数的this在函数定义的时候就已经确定了,它的this指向的是它的外层作用域this的指向。
{
var b = 100;
const a = {
b :200,
test:function A(){
var B = () => {
var C = () => {
console.log(this.b);//A的上下文,即a(该箭头函数所在环境为A)
}
C();
}
B();
}
}
a.test(); //200
}
{ //obj上下文
var x=11;
var obj={
x:22,
say:()=>{
console.log(this.x); //obj的上下文,即{}包括的环境(该箭头函数所在环境为obj)
}
}
obj.say(); //11
} //obj上下文
二、深入理解
1. 全部转换为call方式
- 第一种和第二种形式的函数可以等价变成fun.call(context,p1,p2),其中context就是this。
func(p1,p2) ==> func.call(undefined,p1,p2)
obj.child.method(p1,p2) ==> obj.child.method.call(obj.child,p1,p2) - 浏览器里面有一条规则:如果传进来的context为null或者undefined,那么window对象就是默认的context,在严格模式下,context是undefined
2. []语法
function fn (){
console.log(this) ;
}
var arr = [fn, fn2];
arr[0](); //this指的是数组arr
- 我们可以把
arr[0]( )
想象为arr.0( )
,虽然后者的语法错了,但是形式与转换代码里的 obj.child.method(p1, p2) 对应上了,于是就可以愉快的转换了:
arr[0]()
假想为arr.0()
然后转换为arr.0.call(arr)
那么里面的 this 就是 arr 了
3. 事件绑定中this指事件本身
三、如何确定 this 的值:
- 看源码中对应的函数是怎么被 call 的(这是最靠谱的办法)
看文档 - console.log(this)