箭头函数中的上下文
箭头函数有几个使用注意点:
- 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
- 不可以使用yield命令,因此箭头函数不能用作Generator函数。
普通函数的上下文是调用使用才能确定的,并且规则很多,但是箭头函数的上下文是定义时候确定的。规则其实很简单,只要理解了,就能应对
字面意思理解箭头函数上下文:箭头函数的上下文依靠的是父作用域函数的上下文,获取箭头函数的上下文this就是,就需要获取定义时候所处的普通函数的作用域,该普通函数的上下文就是箭头函数的上下文,如果所处环境没有普通函数上下文就是window
案例1
window.color = "red" let color = "blue"; let obj = { color: "green", getColor:()=>{ return this.color } } let sayColor = ()=>{ return this.color; } console.log(obj.getColor()) // red console.log(sayColor())//red
obj对象中的getColor函数定义时候所处的位置是obj对象中,obj.color是green,但是obj不是函数,所以getColor内部的this不会主动去找obj.color,继续向上找上下文,没找到就输出window的color为red;sayColor方法父作用域也是window所以输出red
案例二
var a = 200; var obj = { a: 100, fn: function(){ return ()=> { return this.a } } } var obj2 = { a: 300, fn: obj.fn } var fn = obj2.fn() console.log(fn()) // 300
obj对象内部的箭头函数定义在obj对象中的fn普通函数中,因为普通函数的上下文this必须在调用的时候才能确定,所以最后obj2在调用fn函数,obj2的上下文是300,所以箭头函数的父亲的上下文就是300,所以箭头函数的上下文就是300
案例三
function foo() { setTimeout(()=>{ console.log(this.a) },100) } var a = 10; foo.call({a: 20}) //20
箭头函数内部输出的a定义在foo普通函数中,又因为foo普通函数调用的时候call了上下文将一个对象{a:20}指给了foo函数,所以foo函数的上下文就是这个对象,foo.a 就是20,所以箭头函数的this.a也是20