箭头函数的this,让很多人困惑,并且,看了一些文章,也没有说得很清楚。既然是programmer,那就让代码说话
function test1(){
const user = {
first: 'Bob',
test: {
arrowFn: () => {
console.log('arrowFn',this)
},
foo1(){
setTimeout(() => {
console.log('foo1 : ', this);
}, 100);
}
}
,
foo2(){
const arr=()=>console.log('arr', this)
arr()
setTimeout(() => {
console.log('foo2 : ', this);
}, 100);
}
}
user.test.arrowFn();
user.test.foo1()
user.foo2()
}
test1()
上面的代码会输出哪些信息?this分别对应什么对象?
arrowFn Window
arr {first: 'Bob', test: {…}, foo2: ƒ}
foo1 {arrowFn: ƒ, foo1: ƒ}
foo2 {first: 'Bob', test: {…}, foo2: ƒ}
对应上面的输出,通过以下几条原则就可以解释了:
只有function/arrow function才会形成scope(作用域),object无法形成作用域(其实也就是大括号无法形成scope,这一点跟java c#不一样)
arrow function的this是上一个scope中的最近的object,
arrow function在定义的时候确定this,function在运行的时候确定this
分析:
arrowFn的this是window,因为,user和test都是object,object不形成作用域,因此,arrowFn在test1()的作用域范围内,然后再往上找一层也就是window才是arrowFn的this
arr在foo2()内,往上找最近的objec,就是user
foo2()中setTimer的arrow function,是在foo2()中定义的,因此,this对应foo2()的上一层,是user
foo1()中的arrow function,foo1()的上一层是test,因此this是test
不得不说,js这个语言,本来只是作为页面脚本来定位的,没指望它能实现复杂逻辑,但是随着SPA大行其道,js变成一个全功能的客户端开发语言,对标C# dephi。不过一些先天性的问题,比如OOP相关的特性,通过补丁摞补丁的方式进行了补充,导致开发者难以理解和使用,也是很无奈了。