JavaScript中函数的prototype属性并非所有函数都有,仅构造函数(如function Person(){})默认拥有,普通函数和箭头函数没有;in运算符检查整个原型链,但返回true仅表示属性存在,不能可靠判断是否为构造函数。
在 JavaScript 中,in 运算符用于检查某个属性是否存在于对象(包括其原型链)中。当它被用来检查函数的 prototype 属性时,其实存在一个常见误解:函数本身**没有**名为 prototype 的自有属性(普通函数),但 in 仍可能返回 true —— 因为该属性可能来自原型链或构造函数本身的特殊定义。
普通函数(非构造函数或箭头函数)本身不拥有 prototype 属性。执行以下代码会得到 false:
这是因为 foo 是 Function 的实例,它的原型链上也没有 prototype 属性;prototype 是仅对**作为构造函数使用的函数**才由引擎自动添加的自有属性。
当函数被设计为构造函数(即使没被 new 调用),JavaScript 引擎会在创建时为其添加 prototype 属性(除非显式删除)。此时 in 才会返回 true:
立即学习“Java免费学习笔记(深入)”;
function Person() {}in 检查的是整个原型链,但这里 prototype 是 Person 自身的属性,所以成立prototype
delete Person.prototype,则 'prototype' in Person 变为 false
仅靠 'prototype' in fn 并不能可靠判断一个函数是否可被 new 调用。例如:
prototype 会让 in 返回 true,但这不代表它是语言层面的构造函数class)声明的函数也有 prototype,且不可枚举,in 依然能检测到typeof、fn.prototype?.constructor === fn 或运行时 new.target 检测若目标是确认函数是否具备构造能力或是否被设计为构造器,in 运算符不是最佳选择。推荐做法:
typeof fn === 'function' 和 fn.prototype && typeof fn.prototype === 'object'
Object.prototype.toString.call(fn) === '[object Function]' 辅助识别in 判断 prototype 存在性——它容易受手动修改干扰,且无法区分“原生构造函数”和“伪构造函数”不复杂但容易忽略:函数的 prototype 是引擎在特定上下文(如函数声明、类定义)中赋予的,不是所有函数都天然具备,in 只反映属性是否存在,不反映语义意图。