7、JavaScript 里居然有 8 种函数?你可能只用过一半!

1,070 阅读3分钟

很多前端写了多年 JS,心里可能一直觉得:
👉 “函数不就是 function 和箭头函数吗?”

真相是:在 ES2018 里,JavaScript 已经进化出至少 8 种函数形态
如果你只会两三种,那面试时很容易被问懵。今天我们就来一次全面盘点。

  • ES2018 中的函数家族(至少 8 种):

    1. 普通函数(function)
    2. 箭头函数(arrow function)
    3. 方法(class 内定义的函数)
    4. 生成器函数(function*)
    5. 类(class,本质上也是函数)
    6. 异步普通函数(async function)
    7. 异步箭头函数(async () => {})
    8. 异步生成器函数(async function*)
  • 它们的区别主要在 this 的行为:

    • 普通函数:this 由调用方式决定;
    • 箭头函数:this 继承自定义时环境;
    • class 方法:默认严格模式,单独赋值后调用可能是 undefined
  • JavaScript 内部机制:

    • 函数有私有属性 [[Environment]] 保存定义时环境;
    • 执行上下文切换时,[[thisMode]] 决定 this 的绑定(lexical/global/strict);
  • 内置操作 this 的方法:callapplybind

  • 只有普通函数和类能与 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 坑过?
欢迎留言分享,让更多人少踩坑!