今天仿一个游戏,全部用的ES6的箭头函数,报错一大堆。看了几篇介绍箭头函数的总结,感觉有一篇写的还可以。Ps:萧大说的真的没错啊 箭头函数真的是个垃圾。。
箭头函数没有this
箭头函数没有this,那下面的代码明显可以取到this啊:
function foo() {
this.a = 1
let b = () => console.log(this.a)
b()
}
foo() // 1
以上箭头函数中的this其实是父级作用域中的this,即函数foo的this。箭头函数引用了父级的变量,构成了一个闭包。以上代码等价于:
function foo() {
this.a = 1
let self = this
let b = () => console.log(self.a)
b()
}
foo() // 1
箭头函数不仅没有this,常用的arguments也没有。如果你能获取到arguments,那它一定是来自父作用域的。
function foo() {
return () => console.log(arguments[0])
}
foo(1, 2)(3, 4) // 1
以上代码中,箭头函数中的this并不是指向a这个对象。对象a并不能构成一个作用域,所以再往上到达全局作用域,this就指向全局作用域。如果我们使用普通函数的定义方法,输出结果就符合预期,这是因为a.bar()函数执行时作用域绑定到了a对象。
let a = {
foo: 1,
bar: function() { console.log(this.foo) }
}
a.bar() // 1
另一个错误是在原型上使用箭头函数,如:
function A() {
this.foo = 1
}
A.prototype.bar = () => console.log(this.foo)
let a = new A()
a.bar() //undefined
同样,箭头函数中的this不是指向A,而是根据变量查找规则回溯到了全局作用域。同样,使用普通函数就不存在问题。
通过以上说明,我们可以看出,箭头函数除了传入的参数之外,真的是什么都没有!如果你在箭头函数引用了this、arguments或者参数之外的变量,那它们一定不是箭头函数本身包含的,而是从父级作用域继承的。
以上决策图看起来有点复杂,我认为有三点比较重要:
箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下,例如用在map、reduce、filter的回调函数定义中;
不要在最外层定义箭头函数,因为在函数内部操作this会很容易污染全局作用域。最起码在箭头函数外部包一层普通函数,将this控制在可见的范围内;
如开头所述,箭头函数最吸引人的地方是简洁。在有多层函数嵌套的情况下,箭头函数的简洁性并没有很大的提升,反而影响了函数的作用范围的识别度,这种情况不建议使用箭头函数。