javascript中函数的prototype属性并非所有函数都有,仅构造函数(如function person(){})默认拥有,普通函数和箭头函数没有;in运算符检查整个原型链,但返回true仅表示属性存在,不能可靠判断是否为构造函数。

在 JavaScript 中,in 运算符用于检查某个属性是否存在于对象(包括其原型链)中。当它被用来检查函数的 prototype 属性时,其实存在一个常见误解:函数本身**没有**名为 prototype 的自有属性(普通函数),但 in 仍可能返回 true —— 因为该属性可能来自原型链或构造函数本身的特殊定义。
函数对象默认没有 prototype 属性
普通函数(非构造函数或箭头函数)本身不拥有 prototype 属性。执行以下代码会得到 false:
console.log('prototype' in foo); // false
这是因为 foo 是 Function 的实例,它的原型链上也没有 prototype 属性;prototype 是仅对**作为构造函数使用的函数**才由引擎自动添加的自有属性。
只有构造函数才有 prototype 属性
当函数被设计为构造函数(即使没被 new 调用),JavaScript 引擎会在创建时为其添加 prototype 属性(除非显式删除)。此时 in 才会返回 true:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
console.log('prototype' in Person); // true
console.log(Person.hasOwnProperty('prototype')); // true
-
in检查的是整个原型链,但这里prototype是Person自身的属性,所以成立 - 箭头函数、普通声明/表达式函数(未用作构造)不会自动获得
prototype - 如果手动删除:
delete Person.prototype,则'prototype' in Person变为false
in 不适合判断“能否用作构造函数”
仅靠 'prototype' in fn 并不能可靠判断一个函数是否可被 new 调用。例如:
regularFn.prototype = {}; // 手动添加
console.log('prototype' in regularFn); // true
new regularFn(); // 可运行,但语义上不是标准构造函数
- 手动赋值
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 只反映属性是否存在,不反映语义意图。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










