面试官:箭头函数和普通函数区别

2,226 阅读3分钟

总结

特性箭头函数普通函数
this 绑定继承定义位置的上下文 (词法作用域)由调用方式决定(调用者)
构造函数调用不支持,不能使用 new支持,可以使用 new
arguments 对象没有 arguments,需使用 rest 参数获取有自己的 arguments 对象
隐式返回支持单行隐式返回不支持,必须使用 return
作为对象方法使用不推荐,因为 this 绑定到外部作用域推荐,this 绑定到调用对象
性能略微节省内存,因无 this 绑定和 arguments性能稳定,尤其在需要绑定上下文时
bind/call/apply不生效,this 永远指向定义时的上下文支持,可动态绑定 this

1. 作用域中的 this 绑定

  • 箭头函数:箭头函数不会创建自己的 this,而是从定义位置的上下文中继承 this 值。这意味着箭头函数中的 this 指向的是它外层最近的非箭头函数的 this,即词法作用域
  • 普通函数:普通函数在调用时会动态地决定 this 的指向。它的 this 指向由调用者决定,例如通过直接调用(指向全局对象)、对象方法调用(指向该对象)、构造函数调用(指向新实例)等。

示例:

const obj = {
  value: 10,
  arrowFunc: () => console.log(this.value), // undefined in non-strict mode
  regularFunc() {
    console.log(this.value); // 10
  }
};

obj.arrowFunc(); // undefined
obj.regularFunc(); // 10

在箭头函数中,this.value 未被定义,因为箭头函数继承的是外部环境的 this,而非 obj 本身。

2. 使用 new 调用

  • 箭头函数:不能作为构造函数使用。如果使用 new 调用箭头函数会抛出错误。
  • 普通函数:可以作为构造函数使用,实例化新对象时 this 指向该新实例。

示例:

const ArrowFunc = () => {};
function RegularFunc() {}

new RegularFunc(); // 正常执行
new ArrowFunc(); // 报错:ArrowFunc is not a constructor

3. arguments 对象的处理

  • 箭头函数:箭头函数没有 arguments 对象。需要使用 rest 参数 (...args) 来获取参数数组。
  • 普通函数:普通函数内有自己的 arguments 对象,可以通过它访问传入的所有参数。

示例:

function regularFunc() {
  console.log(arguments); // [1, 2, 3]
}

const arrowFunc = (...args) => {
  console.log(args); // [1, 2, 3]
};

regularFunc(1, 2, 3);
arrowFunc(1, 2, 3);

4. 隐式返回

  • 箭头函数:箭头函数可以简化写法,对于单行表达式可以省略 {}return 关键字,直接返回结果。
  • 普通函数:普通函数必须显式地使用 return 关键字返回结果。

示例:

const add = (a, b) => a + b; // 隐式返回
function addRegular(a, b) {
  return a + b; // 必须使用 return
}

5. 作为对象方法使用

  • 箭头函数:箭头函数不适合直接作为对象方法,因为它没有自己的 thisthis 会指向定义位置的外部上下文,而不是调用它的对象。
  • 普通函数:普通函数更适合作为对象方法,因为它的 this 会指向调用者,即该对象。

示例:

const obj = {
  value: 42,
  arrowFunc: () => console.log(this.value), // `this` 绑定到外部作用域
  regularFunc() {
    console.log(this.value); // `this` 绑定到 obj
  }
};

obj.arrowFunc(); // undefined
obj.regularFunc(); // 42

6. 性能

  • 箭头函数:箭头函数在特定情况下会略微节省内存,尤其是当它们被用于较少的嵌套环境时,因为不需要 thisarguments 的管理。但是差异在绝大多数情况下是微乎其微的。
  • 普通函数:普通函数在某些优化场景下性能可能更好,尤其是函数调用频繁、需要频繁重新绑定 this 的情况。

7. 绑定上下文

  • 箭头函数:无法通过 bind()call()apply() 改变 this 的指向。箭头函数的 this 永远指向定义时的上下文。
  • 普通函数:可以使用 bind()call()apply() 显式改变 this 指向,动态绑定不同的上下文。

箭头函数适用于简短、无 this 需求的函数,而普通函数更适合需要灵活 this 指向和复杂逻辑的场景。