一文讲透箭头函数

news/2024/7/10 0:51:53 标签: js, python, javascript, java, vue
js_content">

前言

最近是校招季,有时会问同学关于箭头函数和普通函数异同,往往能够得到一些表面的回答,但不够全面不够深入。于是写一篇来彻底讲透箭头函数。

箭头函数是ES6引入到JavaScript中的,是一种新式的匿名函数的写法,类似于其他语言中Lambda函数。箭头函数和传统函数有很多的不同,例如作用域、语法写法等等。

函数定义

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

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

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

对于传统函数,你甚至可以在定义之前调用该函数

sum(1, 2)

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

你可以通过函数名,打印出其函数申明

console.log(sum)

输出结果如下:

ƒ sum(a, b) {
  return a + b
}

函数表达式通常可以有个名字,但是也可以是匿名的,意味着函数是没有名字的。

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

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

这时我们将匿名函数赋值给了sum变量,如果这时候在定义之前调用会导致错误:

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指向。然后,你又了解了关于箭头函数的语法优化,例如隐含返回、单个参数省略括号等。


http://www.niftyadmin.cn/n/1252047.html

相关文章

这次送个特别的「送 ipad」

送礼进行时!为反馈广大读者粉丝们的大力支持,本号主特地选了这款2019 新款苹果iPad 作为抽奖礼品,可手捧追剧玩游戏,也可写字撰文搞创作。无论是自己玩,还是当礼物送人,都属精品。赠送规则本次联合抽奖活动…

html css调用自定义字体,css怎么自定义字体样式?

在CSS中,可以通过font-face规则来指定一个用于显示文本的自定义字体。font-face规则允许网页开发者为其网页指定自定义的字体, 通过这种自定义字体的方式,可以消除对用户电脑字体的依赖。css怎么自定义字体样式?前提条件&#xff…

十分钟上手 ES11 新特性

1、可选链操作符(Optional Chaining)可选链 可让我们在查询具有多个层级的对象时,不再需要进行冗余的各种前置校验。日常开发中,当需要访问嵌套在对象内部好几层的属性时,可能就会得到臭名昭著的错误Uncaught TypeErro…

html为什么会多两像素,html - 在Firefox和IE9中可见的表格高度差异约为2像素 - 堆栈内存溢出...

我在Mozilla / IE中遇到布局问题。 我做了两张桌子。 使用float / left right时,它们彼此相邻显示,并且效果很好。 现在唯一的问题是:IE9的右表比firefox高大约两个像素。 可能是什么问题?在CSS的底部,您可以看到我将表…

在腾讯上班是什么样的体验?

在腾讯上班是什么体验?(不要羡慕)如果你也想来腾讯上班,简历发送到 wanqhnice163.com可以为你提供内推

我写 React 的常用套路

前端这几年的发展,经历了移动互联网时代的爆发,出现了以 Angular、React、Vue 为代表的三大前端框架,近日伴随着 Vue 3.0 RC版本的发布,Vue又被推到风口浪尖,它因其入门简单、易上手,一直深受广大前端工程师…

安装CAD2006出现html,win7系统安装cad2006出现已终止CAD2006-Simplifieng安装的解决方法...

win7系统使用久了,好多网友反馈说win7系统安装cad2006出现已终止CAD2006-Simplifieng安装的问题,非常不方便。有什么办法可以永久解决win7系统安装cad2006出现已终止CAD2006-Simplifieng安装的问题,面对win7系统安装cad2006出现已终止CAD2006…

这次送ikbc F410机械键盘+多本红宝书

我们精心准备了一份礼物,希望在未来的日子里,大家能继续陪伴我们前行,我们也将持续为大家带来更好的内容,一起成长为资深前端工程师&前端专家,加油!活动介绍奖品设置:一等奖:ikb…