async函数仍是Function实例,原型链与同步函数一致;其调用返回Promise实例,属性访问发生在Promise.prototype上,而非async函数自身。
异步函数本身是普通函数,它在原型链上的属性访问行为和同步函数完全一致——不因async关键字改变原型结构或查找逻辑。关键在于:**async 函数返回的是 Promise 实例,而 Promise 实例的原型链才是实际参与属性访问的对象**。
声明一个 async 函数:
async function fetchUser() { return { id: 1 }; }
它本质仍是 Function 的实例:
fetchUser instanceof Function → true
fetchUser.__proto__ === Function.prototype → true
Function.prototype.call、bind、toString 等方法执行 const p = fetchUser() 后,p 是 Promise 实例,其原型链为:
立即学习“Java免费学习笔记(深入)”;
p.__proto__ === Promise.prototypePromise.prototype.__proto__ === Object.prototypeObject.prototype.__proto__ === null(链终点)所以当你写 p.then(...) 或 p.catch(...),是在 Promise.prototype 上查找方法,与原始 async 函数体无关。
例如:
async function say() {}say.custom = 'hello';const p = say();console.log(p.custom); // undefined
原因很清晰:
say.custom 是挂在函数对象自身的属性,不是其 prototype 上的p 是 Promise 实例,与 say 函数对象无原型关联__proto__ 向上查,不会跨对象查找“父级函数”的自有属性若需统一增强所有 Promise 实例的能力(如加 .log() 方法),应修改 Promise.prototype:
Promise.prototype.log = function() { return this.then(res => { console.log('Resolved:', res); return res; });};// 使用fetchUser().log(); // ✅ 可行
但要注意:不建议污染原生原型;更稳妥的方式是封装工具函数或使用类继承 Promise(需重写 constructor 并正确设置原型链)。