javascript中数值原始值无原型链,但调用方法时会临时包装为number实例并访问number.prototype;object.getprototypeof(42)返回number.prototype,其原型为object.prototype,终点为null。

JavaScript 中的数值对象(如 Number、String、Boolean)在被当作对象使用时,会临时包装成对应的包装类型实例,此时它们的原型链就“浮现”出来——但这不是永久状态,也不等同于原始值本身。所谓“隐藏原型链”,其实是原始值与包装对象之间的自动转换机制带来的表象,并非真正隐藏,而是按需触发、不可直接修改。
数值原始值没有原型链,但可临时访问
数字字面量(如 42、3.14)是原始值(primitive),不具有属性或方法,也没有 __proto__。但当你调用 42.toString() 时,JS 引擎会立即做一件事:把 42 临时包装为 new Number(42) 的实例,然后在其原型链上查找 toString 方法。
-
42.__proto__在严格模式下会报错(语法错误),因为点号不能直接跟在数字字面量后;但(42).__proto__或Object.getPrototypeOf(42)是合法的,返回Number.prototype -
Object.getPrototypeOf(42) === Number.prototype→ true - 这个包装过程是瞬时的、不可观测的,包装对象用完即弃,不会影响原始值
Number.prototype 是数值方法的实际来源
所有数值能调用的方法(toFixed、toPrecision、valueOf 等)都定义在 Number.prototype 上。它本身是一个普通对象,其原型是 Object.prototype,再往上就是 null。
-
Number.prototype.__proto__ === Object.prototype→ true -
Object.prototype.__proto__→ null(原型链终点) - 你可以验证:
42.hasOwnProperty是undefined,但(42).hasOwnProperty会报错(因为包装对象没继承该方法),而Object(42).hasOwnProperty就可用——说明包装行为有细微差异
避免误以为“数值对象”可持久扩展
虽然 let n = new Number(42) 创建的是真正的对象实例,但它和原始值 42 行为不同:前者可添加属性,后者永远不可。
-
let n = new Number(42); n.custom = 'ok'; console.log(n.custom)→ 'ok' -
let p = 42; p.custom = 'ok'; console.log(p.custom)→ undefined(赋值静默失败) - 这种差异源于:原始值被包装时生成的是**临时、不可保留**的对象,不是你创建的那个
new Number实例
检查数值相关原型链的可靠方式
不要依赖 __proto__(非标准且易被污染),应使用标准 API 探查真实原型关系:
-
Object.getPrototypeOf(42)→Number.prototype -
Object.getPrototypeOf(Number.prototype)→Object.prototype -
Object.getOwnPropertyNames(Number.prototype)可列出所有可枚举方法名(如toString、toFixed) -
Object.getOwnPropertyDescriptors(Number.prototype)能看到每个方法的enumerable: false等细节——这也是为什么for...in遍历不到这些方法











