asyncfunction 和 generatorfunction 的原型链均直接指向 function.prototype,而非彼此继承,二者区别源于内部槽[[functionkind]]和执行逻辑,检测应优先使用 object.prototype.tostring.call()。

要追溯 AsyncFunction 和 GeneratorFunction 的原型根源,关键不是靠手动遍历 __proto__ 链去“猜”,而是理解它们在 JavaScript 引擎中的构造本质——它们都是函数对象,但由不同内置构造器创建,其原型链最终都指向 Function.prototype,而非彼此继承。
AsyncFunction 的原型链来源
async function 声明或 async () => {} 表达式,底层由引擎隐式调用 AsyncFunction 构造器(非全局可访问,但规范定义存在)。它的实例是函数对象,满足:
- 其
[[FunctionKind]]内部槽为"async" -
asyncFn.__proto__ === Function.prototype(直接继承) -
asyncFn.constructor === AsyncFunction(但AsyncFunction本身不可直接引用,Object.getPrototypeOf(asyncFn).constructor通常返回Function,因引擎未暴露该构造器) - 可通过
Object.prototype.toString.call(asyncFn)得到"[object AsyncFunction]",这是类型识别的可靠方式
GeneratorFunction 的原型链来源
function* 声明或 function*() {} 表达式,由 GeneratorFunction 构造器生成(同样不暴露于全局,但规范中存在)。它的实例也是函数对象,特点是:
- 其
[[FunctionKind]]内部槽为"generator" -
genFn.__proto__ === Function.prototype(同样直接继承) -
genFn.constructor在多数引擎中也表现为Function,但Object.prototype.toString.call(genFn)返回"[object GeneratorFunction]" - 可通过
genFn[Symbol.toStringTag]获取字符串标识(如"GeneratorFunction")
为什么不能靠 __proto__ 链区分二者?
因为两者都不是对方的子类,也不共享独立的中间原型。它们的原型链结构高度一致:
asyncFn → Function.prototype → Object.prototype → nullgenFn → Function.prototype → Object.prototype → null- 没有
AsyncFunction.prototype或GeneratorFunction.prototype这样的公共原型对象(不像Array.prototype那样可扩展) - 所有行为差异(如能否
await、能否next())来自内部属性和执行逻辑,而非原型方法
实用检测方式(推荐替代 __proto__ 追溯)
比起层层读 __proto__,更可靠、更标准的做法是:
- 用
Object.prototype.toString.call(fn)判断:结果为"[object AsyncFunction]"或"[object GeneratorFunction]" - 检查
fn.constructor.name(部分环境返回"AsyncFunction"或"GeneratorFunction",但不保证跨引擎一致) - 结合行为试探:调用
fn()后看返回值是否为Promise(async)或具有next方法的对象(generator) - ES2015+ 环境可用
fn[Symbol.toStringTag]直接读取类型标签
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











