箭头函数与常规函数的 5 个不同

箭头函数与常规函数

在 JavaScript 中,可以使用许多的方法声明函数。首先通常方法是使用 function 关键字:

// 函数声明
function greet(who) {
  return `Hello, ${who}!`;
}
// 函数表达式
const greet = function (who) {
  return `Hello, ${who}`;
};

我将函数声明和函数表达式称之为常规函数

第二种方式是在 ES2015 中加入的箭头函数语法

const greet = (who) => {
  return `Hello, ${who}!`;
};

面对两种声明函数的常规与箭头语法,你是否使用其中的一种替代另一种呢?这是个有意思的问题。

在这篇文章中,我将展示这两者之间的主要不同,让你能够在需要时选择正确的语法。

#this 的值

#常规函数

在 JavaScript 常规函数中,this 的值(又称为执行上下文)是动态的。

动态的上下文意味着 this 的值依赖于该函数是如何被引用的。在 JavaScript 中,有 4 种方式引用常规函数。

简单引用this 的值等价于全局对象(或者 undefined,如果该函数运行在严格模式下):

function myFunction() {
  console.log(this);
}

// 简单引用
myFunction(); // 输出全局对象(window)

方法引用this 的值为拥有该方法的对象:

const myObject = {
  method() {
    console.log(this);
  },
};
// 方法引用
myObject.method(); // 输出 "myObject"

在使用 myFunc.call(context, arg1, ..., argN)myFunc.apply(context, [arg1, ..., argN])间接引用this 的值等价于第一个参数:

function myFunction() {
  console.log(this);
}

const myContext = { value: 'A' };

myFunction.call(myContext); // 输出 { value: 'A' }
myFunction.apply(myContext); // 输出 { value: 'A' }

构造函数引用中使用 new 关键字的 this 等价于新创建的实例:

function MyFunction() {
  console.log(this);
}

new MyFunction(); // 输出一个 MyFunction 的实例

#箭头函数

箭头函数内部 this 的行为与常规函数的 this 行为有很多的不同。

无论怎样或在任意地方被执行,箭头函数内部 this 的值总是等价于它外部的函数的 this 值。一句话,箭头函数绑定 this 解析。换句话说,箭头函数不能声明它自己的执行上下文。

在下面的例子,myMethod() 是在函数 callback() 外部的箭头函数:



 

 







const myObject = {
  myMethod(items) {
    console.log(this); // 输出 "myObject"
    const callback = () => {
      console.log(this); // 输出 "myObject"
    };
    items.forEach(callback);
  },
};

myObject.myMethod([1, 2, 3]);

箭头函数 callback() 内部的 this 值等价于外部函数 myMethod()this 值。

this 绑定解析是箭头函数一个巨棒的功能。当在方法内部使用回调函数时可以确认箭头函数不声明它自己的 this:不再需要使用 const self = thiscallback.bind(this) 之类的变通技巧。

#构造函数

#常规函数

如同上面章节所见,常规函数很容易创建构建函数。举例来说,创建 Car() 函数的实例 car:

function Car(color) {
  this.color = color;
}

const redCar = new Car('red');
redCar instanceof Car; // => true

Car 是一个常规函数,并且使用 new 关键字,它创建属于 Car 类型的新实例。

#箭头函数

一件重要的事是 this 绑定解析的箭头函数不能被用于构造函数。

如果尝试在箭头函数前面使用 new 关键字,JavaScript 将抛出一个错误:

const Car = (color) => {
  this.color = color;
};

const redCar = new Car('red');
// TypeError: Car is not a constructor

#arguments 对象

#常规函数

在常规函数的内部,arguments 是一个特别的类数组对象,该对象包含函数引用的参数列表。

让我们引用 2 个参数运行 myFunction 函数:

function myFunction() {
  console.log(arguments);
}

myFunction('a', 'b'); // 输出 { 0: 'a', 1: 'b'}

类数组对象 arguments 包含函数运行参数:'a''b''

#箭头函数