最直接可靠的函数类型检测方式是 typeof,它对所有函数返回 "function";但需精细区分子类型或应对代理/重写等边界时,需结合其他方法:instanceof Function 易受原型链污染和跨 iframe 影响,constructor === Function 极易被覆盖,Object.prototype.toString.call() 最严谨但无法细分函数种类且略低效。

检测函数类型最直接、最可靠的方式是 typeof,它对函数返回 "function",这是它在所有检测方法中独有的优势。但若需更精细判断(比如区分普通函数、箭头函数、异步函数、生成器函数),或应对某些边界情况(如被代理、被重写构造器的函数),单靠一种方式就不够了。下面介绍四种常用方案及其关键局限。
typeof:基础且高效,但仅限“函数”大类
它能准确识别函数字面量、函数声明、箭头函数、async/await 函数、生成器函数等所有可调用对象,统一返回 "function"。
-
✅ 优点:性能高、语法简洁、对基本函数类型全覆盖;可用于快速排除非函数值(如
typeof fn === 'function') -
❌ 局限:无法区分函数子类型(例如
() => {}和function*() {}都是"function");typeof class {}也返回"function"(因类本质是语法糖函数);不能用于检测函数内部结构或行为特征
instanceof Function:依赖原型链,易受污染
通过检查对象是否为 Function 构造函数的实例来判断,适用于常规函数对象。
-
✅ 优点:语义清晰,能与自定义函数类继承体系配合(如子类继承
Function) -
❌ 局限:对字面量函数(
function() {})有效,但对箭头函数、绑定函数(fn.bind())、代理函数(new Proxy(fn, {}))可能失效;跨 iframe 时因不同全局环境的Function构造器不等价而返回false;不能检测基本类型(1 instanceof Function恒为false)
constructor === Function:直观但脆弱
检查对象的 constructor 属性是否严格等于 Function。
- ✅ 优点:写法直白,对大多数原生函数有效
-
❌ 局限:极易被覆盖——只要函数原型被重赋值(如
fn.constructor = null或Object.setPrototypeOf(fn, {})),结果即不可信;箭头函数没有prototype,其constructor实际继承自Function.prototype,但某些 polyfill 或压缩工具可能干扰该链;同instanceof,跨上下文失效
Object.prototype.toString.call():最严谨的兜底方案
调用原生 Object.prototype.toString 并用 call 绑定目标值,可获得标准类型标签,对函数返回 "[object Function]"。
-
✅ 优点:不受原型链篡改影响;跨 iframe 安全(因调用的是原生
toString方法);能稳定识别所有函数形式,包括箭头函数、异步函数、生成器函数、类、bind 后函数、Proxy 包裹函数 -
❌ 局限:无法进一步细分函数种类(仍统一为
"[object Function]");相比typeof略微低效(涉及方法调用和字符串解析);需封装使用才便于阅读(如toString.call(fn) === '[object Function]')
实际开发中,优先用 typeof fn === 'function' 做快速判断;需要更高鲁棒性(如库开发、插件系统)时,应切换至 Object.prototype.toString.call(fn) === '[object Function]'。其他两种方式除非有特定上下文需求,否则不建议作为主检测逻辑。


















