JavaScript 箭头函数和普通函数有什么区别

2026/07/14

普通函数和箭头函数最容易被问到的区别,还是 this。但只说一句“箭头函数没有自己的 this”还不够,实际还会牵扯到 argumentsprototype、能不能被 new,以及适合用在哪里。

我一般会把它们当成两种不同定位的函数来记:普通函数更完整,可以作为方法、构造函数使用;箭头函数更轻,适合回调和保留外层 this

this 指向不同

普通函数的 this 是调用时决定的:

const obj = {
  name: 'Alice',
  sayHi: function () {
    console.log(this.name);
  },
};

obj.sayHi(); // Alice

这里是 obj.sayHi() 调用,所以 this 指向 obj

箭头函数没有自己的 this,它会捕获定义时外层作用域的 this

const obj = {
  name: 'Alice',
  sayHi: () => {
    console.log(this.name);
  },
};

obj.sayHi(); // 通常不是 Alice

这也是为什么我不太会在对象方法里写箭头函数。它不会因为被 obj 调用就把 this 变成 obj

箭头函数不能作为构造函数

普通函数可以配合 new 创建实例:

function User(name) {
  this.name = name;
}

const user = new User('Alice');

箭头函数不行:

const User = (name) => {
  this.name = name;
};

new User('Alice'); // TypeError: User is not a constructor

因为箭头函数没有自己的 this,也没有作为构造函数需要的内部机制。

prototype 不同

普通函数有 prototype,可以给实例挂原型方法:

function User(name) {
  this.name = name;
}

User.prototype.sayHi = function () {
  console.log(this.name);
};

箭头函数没有 prototype

const fn = () => {};
console.log(fn.prototype); // undefined

所以如果我要写构造函数、原型方法,普通函数才是合适的选择。

arguments 不同

普通函数有自己的 arguments

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

fn(1, 2, 3);

箭头函数没有自己的 arguments,它拿到的是外层函数的 arguments

function outer() {
  const arrow = () => {
    console.log(arguments);
  };

  arrow(1, 2);
}

outer(10, 20); // 输出的是 outer 的 arguments

如果箭头函数里要拿参数,我更倾向于直接用剩余参数:

const fn = (...args) => {
  console.log(args);
};

事件监听里也要注意

如果需要在事件回调里通过 this 获取当前元素,普通函数更合适:

button.addEventListener('click', function () {
  console.log(this); // button
});

箭头函数里的 this 不会指向按钮:

button.addEventListener('click', () => {
  console.log(this); // 来自外层作用域
});

当然,如果用 event.currentTarget,就不一定依赖 this 了:

button.addEventListener('click', (event) => {
  console.log(event.currentTarget);
});

实际项目里怎么选

我的习惯是:

  • 对象方法、构造函数、原型方法:用普通函数。
  • 需要动态 this 的场景:用普通函数。
  • 回调、短函数、数组方法:可以用箭头函数。
  • 需要保留外层 this 的场景:箭头函数更方便。

比如在类组件或者某些回调里,箭头函数可以避免手动 bind;但在对象方法和事件普通回调里,如果想依赖当前调用对象,就不要随便换成箭头函数。

所以它们不是谁替代谁,而是适合的场景不同。普通函数更完整,箭头函数更轻量。只要记住“普通函数的 this 看调用,箭头函数的 this 看外层”,大部分题就能判断出来。