如何实现isDefinedWithAsync函数判断函数是否用async语法定义?
实现
isDefinedWithAsync函数的方案 当然可以实现这个函数!咱们一步步来拆解怎么做:
首先得明确:用async function或async箭头函数定义的函数,本质是AsyncFunction类型的实例,和普通Function构造函数创建的函数是不同的类型。不过有个小细节:全局环境并没有直接暴露AsyncFunction构造函数,但我们可以通过一个匿名async函数的constructor属性来获取它的引用。
基础实现(覆盖核心场景)
先看最直接的版本,利用构造函数匹配来判断:
// 先获取AsyncFunction的引用 const AsyncFunction = (async () => {}).constructor; function isDefinedWithAsync(fn) { // 先校验输入是否为函数 if (typeof fn !== 'function') return false; // 对比构造函数是否为AsyncFunction return fn.constructor === AsyncFunction; }
测试你给出的示例场景:
console.log(isDefinedWithAsync(async function() { return null; })); // true console.log(isDefinedWithAsync(function() { return null; })); // false console.log(isDefinedWithAsync(async () => null)); // true console.log(isDefinedWithAsync(() => null)); // false
完全符合你的要求!
处理边缘情况:绑定后的async函数
上面的方法有个小局限:如果是用bind()绑定后的async函数,它的constructor会变成普通的Function,导致判断失效。比如:
const originalAsync = async function() {}; const boundAsync = originalAsync.bind({}); console.log(isDefinedWithAsync(boundAsync)); // 用基础方法会返回false,但它本质是async函数绑定而来
这时候我们可以结合函数的toString()输出来补充判断——绑定后的async函数,其字符串形式会包含bound async function字样;async箭头函数绑定后也会保留async标识。我们可以优化函数,同时覆盖这两种情况:
const AsyncFunction = (async () => {}).constructor; function isDefinedWithAsync(fn) { if (typeof fn !== 'function') return false; // 优先检查构造函数(处理未绑定的原生async函数) if (fn.constructor === AsyncFunction) { return true; } // 处理绑定后的async函数,匹配各种async定义的字符串形式 const fnStr = fn.toString().trim(); return /^(bound\s+)?async\s+(function|\([^)]*\)\s*=>)|(bound\s+)?async\s*\([^)]*\)\s*=>|(bound\s+)?async\s+\w+\s*=>/.test(fnStr); }
这个优化版本既能处理你给出的核心场景,也能正确识别绑定后的async函数。
注意事项
- 极端压缩场景:如果代码被极度混淆压缩(比如
async关键字被替换),基于toString()的判断可能失效,但这种情况在日常开发中非常少见。 - 不要用返回值判断:普通函数也可以手动返回Promise,这无法区分是否是用
async语法定义的函数。
内容的提问来源于stack exchange,提问作者Gershom Maes
相关产品推荐
相关产品推荐

