掌握javascript原型机制的关键是分清“谁属于谁”和“谁该用谁”:__proto__是历史遗留接口,object.getprototypeof()和object.setprototypeof()才是标准、安全、可预测的正道。

掌握 JavaScript 原型机制,关键不是记住三个名字,而是分清“谁属于谁”和“谁该用谁”。__proto__ 是历史遗留的访问通道,Object.getPrototypeOf() 和 Object.setPrototypeOf() 才是标准、安全、可预测的正道。用错地方,轻则代码行为不一致,重则跨环境失效、性能骤降甚至静默失败。
__proto__ 本质:只是 [[Prototype]] 的读写接口
每个对象内部都有一个不可见的 [[Prototype]] 内部槽,它真正决定属性查找路径。而 __proto__ 只是浏览器为方便调试暴露出来的 getter/setter —— 它不是语言规范定义的正式 API,而是附录级兼容特性。
- 读取时:
obj.__proto__等价于Object.getPrototypeOf(obj)(在支持环境中) - 写入时:
obj.__proto__ = proto等价于Object.setPrototypeOf(obj, proto),但可能触发引擎优化禁用 -
__proto__在严格模式下赋值会静默失败(不报错但无效),而Object.setPrototypeOf()会明确抛出 TypeError 或返回 false
getPrototypeOf:唯一推荐的“读原型”方式
它稳定、跨平台、不依赖运行时环境实现,且行为完全由 ECMAScript 规范定义。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 对普通对象:返回其构造函数的 prototype(如
Object.getPrototypeOf({}) === Object.prototype) - 对
Object.create(null)创建的对象:返回null(这是唯一原生返回 null 的情况) - 对原始值(字符串、数字等):先包装成对象再取其构造器 prototype(如
Object.getPrototypeOf(42) === Number.prototype) - 对
null或undefined:直接抛TypeError,不会尝试转换
setPrototypeOf:唯一安全的“改原型”入口
手动修改原型是高风险操作,应尽量避免;但若必须做(如模拟继承、框架元编程),务必只用这个方法。
- 第一个参数必须是对象,否则直接返回原值(如
Object.setPrototypeOf(123, {})返回123) - 第二个参数可以是对象或
null,但不能是原始值(传入字符串/数字会报错) - 成功返回目标对象;失败(如冻结对象、不可扩展对象)会抛
TypeError - 慎用于已有大量属性/方法的对象——V8 等引擎可能因此降级为慢路径,影响性能
避坑清单:这些事千万别做
很多看似“能跑”的写法,实则是埋雷。
- 别用
obj.__proto__ = ...初始化继承关系——改用Object.setPrototypeOf(child, parent)或更优的Object.create(parent) - 别依赖
obj.constructor.prototype判断类型——constructor 可被篡改,而Object.getPrototypeOf(obj)始终真实 - 别在循环中反复调用
Object.setPrototypeOf()——原型链一旦建立就应保持稳定 - 别对
Array.prototype、Object.prototype等原生原型做任何修改——污染全局环境,极易引发不可预知冲突
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










