箭头函数

箭头函数要实现类似纯函数的效果,必须剔除外部状态。所以当你定义一个箭头函数,在普通函数里常见的 thisargumentscaller 是统统没有的。

箭头函数没有 this

箭头函数没有 this ,那下面的代码明显可以取到 this 啊:

function foo() {
  let a = 1
  let b = () => console.log(this.a)

  b()
}
foo()  // 1

以上箭头函数中的 this 其实是父级作用域中的 this ,即函数 foo 的 this 。箭头函数引用了父级的变量,构成了一个闭包。以上代码等价于:

function foo() {
  let a = 1
  let self = this
  let b = () => console.log(self.a)
  b()
}
foo()  // 1

一个经常犯的错误是使用箭头函数定义对象的方法,如:

let a = {
  foo: 1,
  bar: () => console.log(this.foo)
}
a.bar()  //undefined

以上代码中,箭头函数中的 this 并不是指向 a 这个对象。对象 a 并不能构成一个作用域,所以再往上到达全局作用域, this 就指向全局作用域。


另一个错误是在原型上使用箭头函数,如:

function A() {
  this.foo = 1
}
A.prototype.bar = () => console.log(this.foo)
let a = new A()
a.bar()  //undefined

同样,箭头函数中的 this 不是指向 A ,而是根据变量查找规则回溯到了全局作用域。同样,使用普通函数就不存在问题

箭头函数没有arguments

function foo() {
  return () => console.log(arguments[0])
}
foo(1, 2)(3, 4)  // 1

上例中如果箭头函数有 arguments ,就应该输出的是3而不是1。

通过以上说明,我们可以看出,箭头函数除了传入的参数之外,真的是什么都没有!如果你在箭头函数引用了 this 、 arguments 或者参数之外的变量,那它们一定不是箭头函数本身包含的,而是从父级作用域继承的。

那么问题来了,什么情况下该使用箭头函数

  • 箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下,例如用在 map 、 reduce 、 filter 的回调函数定义中;
  • 不要在最外层定义箭头函数,因为在函数内部操作 this 会很容易污染全局作用域。最起码在箭头函数外部包一层普通函数,将 this 控制在可见的范围内;