一文讲透ES6箭头函数

前言

最近是校招季,有时会问同窗关于箭头函数和普通函数异同,每每可以获得一些表面的回答,但不够全面不够深刻。因而写一篇来完全讲透箭头函数。前端

箭头函数是ES6引入到JavaScript中的,是一种新式的匿名函数的写法,相似于其余语言中Lambda函数。箭头函数和传统函数有不少的不一样,例如做用域、语法写法等等。markdown

函数定义

在深刻介绍箭头函数和传统函数异同以前,咱们先了解一下传统函数的使用,这样将更好的理解箭头函数的异同。app

下面是一个sum函数的定义,能够返回两个参数之和。函数

function sum(a, b) {
  return a + b
}
复制代码

对于传统函数,你甚至能够在定义以前调用该函数oop

sum(1, 2)

function sum(a, b) {
  return a + b
}
复制代码

你能够经过函数名,打印出其函数申明优化

console.log(sum)
复制代码

输出结果以下:this

ƒ sum(a, b) {
  return a + b
}
复制代码

函数表达式一般能够有个名字,可是也能够是匿名的,意味着函数是没有名字的。spa

下面例子是sum函数的匿名申明方式:prototype

const sum = function (a, b) {
  return a + b
}
复制代码

这时咱们将匿名函数赋值给了sum变量,若是这时候在定义以前调用会致使错误:code

sum(1, 2)

const sum = function (a, b) {
  return a + b
}
复制代码

错误返回:Uncaught ReferenceError: Cannot access 'sum' before initialization

咱们也能够把sum打印出来:

const sum = function (a, b) {
  return a + b
}

console.log(sum)
复制代码

打印出来的结果以下:

ƒ (a, b) {
  return a + b
}
复制代码

sum是一个匿名函数,而不是一个有名字的函数。

箭头函数

箭头函数和普通函数有很是多的不一样,其中最大的不一样是箭头函数没有没有本身的this绑定,没有prototype,同时也不能被用作构造函数。同时,箭头函数能够做为普通函数提供更为简洁的写法。

this绑定

在JavaScript中,this每每是一个比较复杂诡异的事情。在JavaScript中有bind、apply、call等方法会影响this所指定的对象。

箭头函数的this是语义层面的,所以,箭头函数中的this是由上下文做用域决定的。下面的例子会解释this在普通函数和箭头函数的区别:

const printNumbers = {
  phrase: 'The current value is:',
  numbers: [1, 2, 3, 4],

  loop() {
    this.numbers.forEach(function (number) {
      console.log(this.phrase, number)
    })
  },
}
复制代码

你也许会指望loop函数会打印出文本和对应的数字,而后真正返回的内容实际上是undefined:

printNumbers.loop()
复制代码

输出:

undefined 1
undefined 2
undefined 3
undefined 4
复制代码

在上面的例子中,this.phrase表明了undefined,说明在forEach方法中的匿名函数中的this并不会指向printNumber对象。这是由于普通函数并非经过上下文做用域来决定this的值,而是经过实际调用函数的对象来决定的。

在老版本的JavaScript,你能够经过bind方法来显示的绑定this。使用bind的方式以下:

const printNumbers = {
  phrase: 'The current value is:',
  numbers: [1, 2, 3, 4],

  loop() {
    // 将外部的printNumber对象绑定到内部forEach函数中的'this'
    this.numbers.forEach(
      function (number) {
        console.log(this.phrase, number)
      }.bind(this),
    )
  },
}

printNumbers.loop()
复制代码

这将输出正确的结果:

The current value is: 1
The current value is: 2
The current value is: 3
The current value is: 4
复制代码

箭头函数提供了一个更为优雅的解决方案,因为其this的指向是由上下文做用域来决定的,所以它会指向printNumbers对象:

const printNumbers = {
  phrase: 'The current value is:',
  numbers: [1, 2, 3, 4],

  loop() {
    this.numbers.forEach((number) => {
      console.log(this.phrase, number)
    })
  },
}

printNumbers.loop()
复制代码

箭头函数做为对象方法

箭头函数在循环中能够很好的使用,可是做为对象方法却会形成问题。

const printNumbers = {
  phrase: 'The current value is:',
  numbers: [1, 2, 3, 4],

  loop: () => {
    this.numbers.forEach((number) => {
      console.log(this.phrase, number)
    })
  },
}
复制代码

调用loop方法

printNumbers.loop()
复制代码

结果会出现以下错误:

Uncaught TypeError: Cannot read property 'forEach' of undefined
复制代码

这是由于在loop箭头函数申明的时候,this指向并不会是printNumbers对象,而是外部的Window。而Window上面并无numbers字段,从而致使错误。所以,对象方法通常使用传统方法。

箭头函数没有Prototype和构造函数

在JavaScript中的Function或者Class中都会有一个Prototype属性,这个能够用于对象拷贝或者继承。

function myFunction() {
  this.value = 5
}

// Log the prototype property of myFunction
console.log(myFunction.prototype)
复制代码

输出:

{constructor: ƒ}
复制代码

可是,箭头函数是不存在Prototype属性,咱们能够尝试打印出箭头函数的Prototype。

const myArrowFunction = () => {}

// Attempt to log the prototype property of myArrowFunction
console.log(myArrowFunction.prototype)
复制代码

输出:

undefined
复制代码

同时,因为没有Prototype属性,所以也无法经过new进行实例化。

const arrowInstance = new myArrowFunction()
console.log(arrowInstance)
复制代码

输出错误:

Uncaught TypeError: myArrowFunction is not a constructor
复制代码

箭头函数除了这些变化以外,还有些语法上的不一样,可让写法变得更简洁。

隐含返回

传统的方法都是须要大括号{},而且经过return语句返回值。

const sum = (a, b) => {
  return a + b
}
复制代码

箭头函数能够简化函数声明,而且提供隐含返回值。

const sum = (a, b) => a + b
复制代码

单个参数省略括号

例如:

const square = (x) => x * x
复制代码

当只有一个参数的时候,能够省略(),写成以下形式:

const square = x => x * x
square(10)
复制代码

输出:100

有些代码库老是尝试忽略(),而有的代码库老是保留,尤为是采用TypeScript的代码库,须要声明每一个参数的类型。所以,你须要首先规定好代码库的风格,而且始终保持。

写在最后

在这篇文章中,你了解了箭头函数和传统函数的区别。箭头函数始终是匿名的,没有Prototype或者构造函数,没法用new进行实例化,而且是经过语义上下文来决定this指向。而后,你又了解了关于箭头函数的语法优化,例如隐含返回、单个参数省略括号等。

『奶爸码农』从事互联网研发工做10+年,经历IBM、SAP、陆金所、携程等国内外IT公司,目前在美团负责餐饮相关大前端技术团队,按期分享关于大前端技术、投资理财、我的成长的思考与总结。

相关文章
相关标签/搜索