深入 JavaScript 原型系统:为什么 typeof Object 是 “function”,而 typeof {} 是 “object”?
·
在学习 JavaScript 的过程中,你是否曾被以下现象困惑过?
typeof Object; // "function"
typeof {}; // "object"
明明 Object 是“对象”的代表,为什么它自己却是个函数?
而 {} 才是我们日常使用的“对象”,却被识别为 "object"?
更令人费解的是,Object 和 Function 之间还存在一种看似“循环引用”的原型关系:
Object.__proto__ === Function.prototype; // true
Function.__proto__ === Function.prototype; // true
本文将带你彻底理清这两个问题背后的机制,揭开 JavaScript 原型系统的神秘面纱。
一、先回答:为什么 typeof Object ≠ typeof {}?
✅ 核心原因:它们根本不是同一类东西!
| 表达式 | 实际类型 | 说明 |
|---|---|---|
Object | 内置构造函数(函数) | 可调用:Object() 或 new Object() |
{} | 普通对象字面量 | 不可调用,是 Object 的实例 |
根据 ECMAScript 规范,typeof 对可调用对象(即具有 [[Call]] 内部方法的对象)返回 "function",否则返回 "object"。
所以:
Object是一个函数 →typeof Object === "function"{}是一个普通对象 →typeof {} === "object"
💡 类比理解:
Object是“造车的工厂”(函数){}是“工厂生产出来的一辆车”(对象)
二、深入:Object 和 Function 的原型关系
要理解上述现象,必须搞懂 JavaScript 中最核心的两个内置对象:Object 和 Function。
1. 基本事实
- 所有函数(包括
Object、Array、Date)都是Function的实例。 - 所有普通对象(包括
{}、[]、Function.prototype)最终都继承自Object.prototype。
因此:
Object instanceof Function; // true
Function instanceof Function; // true
({}).__proto__ === Object.prototype; // true
2. 它们的 __proto__ 指向哪里?
| 表达式 | 值 | 说明 |
|---|---|---|
Object.__proto__ | Function.prototype | Object 是函数,由 Function 构造 |
Function.__proto__ | Function.prototype | Function 自身也是函数 |
Function.prototype.__proto__ | Object.prototype | Function.prototype 是普通对象 |
Object.prototype.__proto__ | null | 原型链终点 |
3. 原型关系图(文字版)
Function ──.__proto__──→ Function.prototype ──.__proto__──→ Object.prototype ──.__proto__──→ null
↑
│ (instanceof)
Object ──.__proto__───────────────────────────────────────┘
🔁 这看起来像“鸡生蛋、蛋生鸡”,但实际上是 JS 引擎在初始化时预定义好的闭环结构。
三、验证代码(建议在控制台运行)
// 1. typeof 差异
console.log(typeof Object); // "function"
console.log(typeof {}); // "object"
// 2. instanceof 验证
console.log(Object instanceof Function); // true
console.log(Function instanceof Function); // true
// 3. __proto__ 关系
console.log(Object.__proto__ === Function.prototype); // true
console.log(Function.__proto__ === Function.prototype); // true
// 4. Function.prototype 是普通对象
console.log(typeof Function.prototype); // "object"
console.log(Function.prototype.__proto__ === Object.prototype); // true
// 5. Object.prototype 是原型链顶端
console.log(Object.prototype.__proto__ === null); // true
四、常见误区澄清
误区1:Object 是最顶层对象,所以 Object.__proto__ 应该是 null
✅ 正解:Object 是函数,不是普通对象。所有函数的 __proto__ 都指向 Function.prototype。
误区2:Function.prototype 是一个函数
✅ 正解:typeof Function.prototype 返回 "object",它是一个内置的普通对象,仅用于被函数实例继承。
误区3:{} 和 Object 是等价的,所以 typeof 应该一样
✅ 正解:{} 是 Object 的实例,就像 new Array() 和 Array 的关系一样——构造函数 vs 实例。
五、延伸:如何正确判断类型?
由于 typeof 对对象一律返回 "object"(连 null 也是!),我们常使用:
Object.prototype.toString.call(value).slice(8, -1)
例如:
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call(new Date()) // "[object Date]"
Object.prototype.toString.call(/regex/) // "[object RegExp]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(123) // "[object Number]"
Object.prototype.toString.call("str") // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(Symbol()) // "[object Symbol]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call({}) // "[object Object]"
这正是利用了 Object.prototype.toString 能返回内部 [[Class]] 标签的特性。
六、总结
| 问题 | 答案 |
|---|---|
为什么 typeof Object 是 "function"? | 因为 Object 是一个可调用的构造函数 |
为什么 typeof {} 是 "object"? | 因为 {} 是一个普通对象实例 |
Object.__proto__ 指向哪? | Function.prototype |
Function.__proto__ 指向哪? | Function.prototype |
| 原型链终点是? | Object.prototype.__proto__ === null |
🌟 记住:
- 函数也是对象,但可调用 →
typeof返回"function"Object是“模具”,{}是“产品”- 整个原型系统由
Object和Function共同构建
参考资料
- ECMAScript® 2024 Language Specification
- MDN:
typeof
更多推荐


所有评论(0)