判断变量是否为可构造函数需满足:是函数类型且prototype为非null对象,并排除箭头函数、async函数、生成器函数等不可构造类型。

要判断一个变量是否为函数 且具有构造函数能力,关键在于两点:一是它得是函数类型,二是它必须能被 new 调用(即不是箭头函数、普通方法或绑定函数等“不可构造”的函数)。
看它能否用 new 调用
JavaScript 中只有部分函数具备构造能力。最直接的验证方式是尝试用 new 实例化它——但实际开发中一般不真执行,而是借助语言规范和运行时特征来判断:
-
不能被 new 的函数:箭头函数、async 函数、生成器函数(
function*)、通过bind()返回的函数、类中的普通方法(非静态) -
能被 new 的函数:传统函数声明/表达式、class 构造器(本质是函数)、带有
prototype且非 null 的函数
检查 prototype 属性是否可写且非 null
一个函数若支持构造调用,其 prototype 属性必须存在且为对象(不能是 undefined 或原始值)。这是 ECMAScript 规范对“可构造函数”的隐含要求:
typeof fn === 'function' && fn.prototype !== undefined && typeof fn.prototype === 'object'- 注意:
fn.prototype可能被人为改写为null或其他值,此时即使原生函数也会失去构造能力
用 instanceof Function 并排除已知不可构造类型
结合类型检查与行为特征,更稳妥的做法是:
- 先确认是函数:
typeof fn === 'function' - 再排除明确不可构造的类型:
!fn[Symbol.hasInstance] && !fn.constructor && !(fn instanceof AsyncFunction) && !(fn instanceof GeneratorFunction)
(需提前获取AsyncFunction和GeneratorFunction,可通过Object.getPrototypeOf(async function(){}).constructor等方式获取) - 最后验证
fn.prototype是否为对象(非 null、非 undefined)
简单实用的判断函数(推荐)
以下是一个兼顾准确性与兼容性的判断逻辑:
function isConstructable(fn) {
if (typeof fn !== 'function') return false;
if (fn.prototype == null || typeof fn.prototype !== 'object') return false;
// 排除箭头函数(无 prototype 且 toString 返回 '() => {}')
if (fn.toString().trim().startsWith('() =>')) return false;
// 排除 async/ generator(现代引擎下 toString 有明确标识)
if (/^(async|function\*)/.test(fn.toString().trim())) return false;
return true;
}
这个函数在绝大多数场景下可靠,包括跨 iframe(因不依赖 instanceof),也覆盖了常见不可构造函数形态。

















