很多前端写了多年 JS,心里可能一直觉得:
👉 “函数不就是 function 和箭头函数吗?”
真相是:在 ES2018 里,JavaScript 已经进化出至少 8 种函数形态!
如果你只会两三种,那面试时很容易被问懵。今天我们就来一次全面盘点。
-
ES2018 中的函数家族(至少 8 种):
- 普通函数(function)
- 箭头函数(arrow function)
- 方法(class 内定义的函数)
- 生成器函数(function*)
- 类(class,本质上也是函数)
- 异步普通函数(async function)
- 异步箭头函数(async () => {})
- 异步生成器函数(async function*)
-
它们的区别主要在
this的行为:- 普通函数:
this由调用方式决定; - 箭头函数:
this继承自定义时环境; - class 方法:默认严格模式,单独赋值后调用可能是
undefined;
- 普通函数:
-
JavaScript 内部机制:
- 函数有私有属性
[[Environment]]保存定义时环境; - 执行上下文切换时,
[[thisMode]]决定 this 的绑定(lexical/global/strict);
- 函数有私有属性
-
内置操作 this 的方法:
call、apply、bind; -
只有普通函数和类能与
new搭配使用。
1. 普通函数
最传统的定义方式:
function foo() { return 42; }
this 的指向由调用方式决定。
2. 箭头函数
ES6 引入的简洁写法:
const foo = () => 42;
this 继承定义时环境,无法被 call/apply/bind 改变。
3. 方法(class 内函数)
在类中定义:
class C {
foo() { console.log(this); }
}
⚠️ 注意:方法默认是 严格模式,单独赋值后调用可能得到 undefined。
4. 生成器函数(function*)
带星号的函数,可以 yield:
function* gen() {
yield 1; yield 2; yield 3;
}
返回迭代器,支持暂停与恢复执行。
5. 类(class)
别忘了:class 本质上也是一个函数。
class Foo {}
console.log(typeof Foo); // function
6-8. 异步函数家族
加上 async 修饰后,立刻变成新的形态:
async function foo() {}
const bar = async () => {};
async function* baz() {}
它们的返回值会自动包装成 Promise,并与 await 联动。
this 的大不同
- 普通函数:调用引用决定
this。 - 箭头函数:
this继承外层环境。 - 方法:默认严格模式,容易“丢失
this”。
示例:
function showThis() { console.log(this); }
const o = { showThis };
o.showThis(); // o
const f = o.showThis;
f(); // global 或 undefined (严格模式)
内部机制揭秘
-
每个函数都带有
[[Environment]],记录定义时作用域。 -
执行时,JS 用
[[thisMode]]来确定 this:- lexical → 箭头函数
- global → 普通函数
- strict → 严格模式 / class 方法
此外,call/apply/bind 能修改普通函数的 this,但对箭头函数无效。
new 与函数
只有 普通函数 和 class 可以与 new 搭配使用,生成实例对象。
这倒是帮我们省去不少歧义。
总结
JavaScript 的函数世界比你想象的更复杂:
- function、箭头函数、方法、生成器、类、异步函数家族……
- this 行为差异巨大,理解它能避免很多 bug。
- 只有普通函数和类能与
new一起使用。
互动问题:
👉 你日常开发里,最常用的是哪几种函数?有没有被 this 坑过?
欢迎留言分享,让更多人少踩坑!