箭头函数与普通函数的区别

对比箭头函数和普通函数在 this、arguments、new 等方面的差异

问题

箭头函数与普通函数有哪些区别?主要从 this 绑定、arguments 对象、new 调用等方面说明。

解答

1. this 绑定

箭头函数没有自己的 this,它会捕获定义时所在上下文的 this。

const obj = {
  name: 'obj',
  
  // 普通函数:this 指向调用者
  regular() {
    console.log(this.name); // 'obj'
  },
  
  // 箭头函数:this 继承外层作用域
  arrow: () => {
    console.log(this.name); // undefined(this 指向全局/外层)
  }
};

obj.regular(); // 'obj'
obj.arrow();   // undefined

常见场景:回调函数中保持 this 指向

function Timer() {
  this.seconds = 0;
  
  // 普通函数:this 丢失
  setInterval(function() {
    this.seconds++; // this 指向 window,不是 Timer 实例
  }, 1000);
  
  // 箭头函数:this 保持指向 Timer 实例
  setInterval(() => {
    this.seconds++; // 正确,this 指向 Timer 实例
  }, 1000);
}

2. arguments 对象

箭头函数没有自己的 arguments,访问的是外层函数的 arguments。

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

const arrow = () => {
  console.log(arguments); // ReferenceError: arguments is not defined
};

regular(1, 2, 3);
arrow(1, 2, 3);

箭头函数中获取参数,使用 rest 参数:

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

arrow(1, 2, 3);

3. 不能作为构造函数

箭头函数没有 [[Construct]] 内部方法,不能使用 new 调用。

function Regular() {
  this.value = 1;
}

const Arrow = () => {
  this.value = 1;
};

new Regular(); // OK
new Arrow();   // TypeError: Arrow is not a constructor

4. 没有 prototype 属性

function regular() {}
const arrow = () => {};

console.log(regular.prototype); // {constructor: f}
console.log(arrow.prototype);   // undefined

5. 不能用作 Generator

箭头函数不能使用 yield 关键字。

// 普通函数可以
function* generator() {
  yield 1;
}

// 箭头函数不行,语法错误
const arrowGen = *() => {
  yield 1;
}; // SyntaxError

6. call/apply/bind 无法改变 this

const obj1 = { name: 'obj1' };
const obj2 = { name: 'obj2' };

const arrow = () => {
  console.log(this.name);
};

arrow.call(obj1);  // undefined(this 不变)
arrow.apply(obj2); // undefined(this 不变)
arrow.bind(obj1)(); // undefined(this 不变)

关键点

  • this:箭头函数没有自己的 this,继承定义时外层作用域的 this,且无法通过 call/apply/bind 修改
  • arguments:箭头函数没有 arguments 对象,需用 rest 参数 ...args 替代
  • 构造函数:箭头函数不能用 new 调用,没有 prototype 属性
  • Generator:箭头函数不能使用 yield,不能作为生成器函数
  • 适用场景:箭头函数适合回调、需要保持 this 的场景;普通函数适合对象方法、构造函数、需要 arguments 的场景