结论:应使用 object.getprototypeof() 和 object.setprototypeof() 而非 proto 编写工业级原型链代码,因前者是标准、语义清晰、可预测且健壮的api,后者仅为遗留兼容特性,存在语义模糊、性能差及静默失败等风险。

直接说结论:不靠 __proto__,靠 Object.getPrototypeOf() 和 Object.setPrototypeOf() 才能写出稳定、可维护、语义清晰的工业级原型链代码。
别碰 __proto__ —— 它不是 API,是历史包袱
__proto__ 是早期浏览器私有实现,虽被 ES6 收录为“遗留特性”,但规范明确指出它不是标准接口,只是兼容性妥协。它语义模糊(看起来像属性,实为访问器)、性能差(每次访问都触发内部查找)、且在严格模式下可能静默失败。工业级代码首要原则是可预测性,而 __proto__ 正好相反。
- 永远不要用
obj.__proto__ = newProto做原型赋值 - 不要用
obj.__proto__读取原型 —— 即使它“能跑”,也掩盖了真实意图 - 构建工具(如 TypeScript + ESLint)应配置规则禁止
__proto__使用
用 getPrototypeOf 显式表达“我想查它的祖先是谁”
Object.getPrototypeOf(obj) 是唯一标准、无副作用、语义精准的读取方式。它返回 obj 的 [[Prototype]],即构造函数的 .prototype 对象,逻辑透明,调试友好。
- 可用于类型判断:
Object.getPrototypeOf(obj) === Array.prototype - 可用于安全继承检查:
Object.getPrototypeOf(child) === parent.prototype - 配合
Object.prototype.isPrototypeOf()可做原型链断言,比instanceof更底层、更可控
用 setPrototypeOf 替代手动赋值,确保行为可预期
Object.setPrototypeOf(obj, proto) 是标准写法,它会触发内部 [[SetPrototypeOf]] 操作,并在不可扩展对象上抛出错误(严格模式下),而不是静默失败 —— 这正是工业级健壮性的体现。
- 替代
obj.__proto__ = X,语义明确:“我要把 obj 的原型设为 X” - 返回目标对象,支持链式调用(虽不推荐滥用,但结构上更函数式)
- 与
Object.create(proto)形成互补:前者改已有对象,后者创建新对象并指定原型 - 注意:频繁调用会影响 V8 等引擎的优化(隐藏类失效),所以只在初始化或明确需要动态委托时使用
真正体现架构美感的是组合而非操作
顶级代码从不“折腾原型”,而是用标准原语构建可推理的结构:
- 用
Object.create(null)创建纯净字典对象,彻底隔离原型污染风险 - 用
class+extends声明继承关系,编译后自动处理setPrototypeOf和getPrototypeOf,语义最直白 - 用
Reflect.getPrototypeOf()替代Object.getPrototypeOf()(尤其在 Proxy 场景中),保持元编程一致性 - 封装原型操作为工厂函数,例如:
createWithDelegate(prototype, props)内部调用Object.create(prototype)+Object.assign,对外隐藏细节











