Javascript 箭头函数和普通函数的区别

685 阅读3分钟

「这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战

Javascript 箭头函数和普通函数的区别

ES6中新提出了箭头函数(Arrow function)的概念。本质上箭头函数肯定是函数,但是拥有一些和普通函数不一样的特性。这篇文章主要是来梳理一下箭头函数和普通函数的区别。

来看看MDN上的定义

箭头函数 
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的thisargumentssupernew.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。

对应英文版的定义

Arrow function expressions

An arrow function expression is a compact alternative to a traditional function expression, but is limited and can't be used in all situations.

可以发现英文原文应该是箭头函数表达式,从这里也可以知道,箭头函数是一种函数表达式,而不是函数声明。

一、 区别

1. 更简洁的语法

箭头函数的函数体可以像普通函数一样用{}包含,也可以采用简写的方法。

  • 简写体中只能写一个表达式,默认将这个表达式作为返回值。
// 块体
let func = a => { return a + a }

// 简写体
let func = a => a + a
  • 当参数只有一个时可以省略(),有多个参数时不可以省略
// 正确
let func = (a) => a + a

// 正确
let func = a => a + a

// 正确
let func = (a, b) => a + b

// 错误
let func = a, b => a + a
  • 返回对象字面量时必须用圆括号把对象字面量包起来
var func = () => { foo: 1 };
// Calling func() returns undefined!

var func = () => { foo: function() {} };
// SyntaxError: function statement requires a name

2. 不会绑定Arguments对象

箭头函数中不会绑定Arguments对象,取而代之应该使用rest剩余参数,也就是...运算符。

// 无法获取到正确的参数
let func = () => {
    console.log(arguments)
}

func(1,2)
// 正确
let func = (...args) => {
    console.log(args)
}

func(1,2)

3. 没有属于自己的this

  • 箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。
  • 一经绑定就不能再改变。
  • 通过 call 或 apply 调用可以执行但不会生效。
var fruit = 'apple'

let person = {
    name: 'Alice',
    fruit: 'orange',
    getName: function () {
        console.log(this.name)
    },
    getFruit: () => {
        console.log(this.fruit)
    }
}

person.getName() // Alice
person.getFruit()  // apple

4. 没有prototype属性

let func = a => a + a
console.log(func.prototype); // undefined

5. 不能用作构造函数

箭头函数不能用作构造函数,即不能通过new进行实例化。

image.png

- 为什么箭头函数不能用作构造函数?

从new关键字的操作分析:

  1. 创建一个空的简单JavaScript对象(即{})
  2. 链接该对象的原型到构造函数的prototype
  3. 将步骤1新创建的对象作为this的上下文
  4. 如果该函数没有返回对象,则返回this

可以发现,因为箭头函数没有自己的this,没有prototype,所以无论是链接还是绑定都无法正常完成。

6. 不能用作生成器

yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作函数生成器。

7. 没有属于自己的super

箭头函数中也是没有属于自己的super,具体的原因没有找到,有了解的大佬可以交流交流。

8. 没有new.target 关键字

new.target 属性允许你检测函数或构造方法是否是通过new运算符被调用的。在通过new运算符被初始化的函数或构造方法中,new.target返回一个指向构造方法或函数的引用。在普通的函数调用中,new.target 的值是undefined

9. 使用箭头函数作为方法

和上述第三点中提到的,因为箭头函数没有自己的this,在捕获外层作用域的this时,this的指向不会发生改变。箭头函数作为方法,this的指向会比较符合预期。