javascript对象原型可通过object.setprototypeof()或构造函数prototype动态挂载,前者兼容性好、语义清晰,后者适用于批量实例;慎用__proto__,因其非标准且影响性能;挂载受对象状态及属性遮蔽限制。

JavaScript对象的原型可以通过修改其__proto__属性或构造函数的prototype来动态挂载,但要注意方式和时机——直接改实例的__proto__虽可行,但不推荐;更安全的做法是通过构造函数或Object.setPrototypeOf()统一设置。
用 Object.setPrototypeOf() 动态挂载原型
这是ES6标准推荐的方式,用于在运行时为已有对象设置新原型,且兼容性好、语义清晰:
- 语法:
Object.setPrototypeOf(obj, newPrototype) - 只能对普通对象调用,不能对冻结对象或不可扩展对象生效(会静默失败或抛错)
- 示例:
const obj = {};<br> const proto = { sayHi() { return 'hello'; } };<br> Object.setPrototypeOf(obj, proto);<br> console.log(obj.sayHi()); // 'hello'
通过构造函数 prototype 挂载(适用于批量实例)
如果对象由构造函数创建,修改其构造函数的prototype可让所有后续实例自动继承新方法:
- 注意:已创建的实例不会自动更新(除非它们还没访问过该属性,且原型链未被切断)
- 新增方法后,新实例和部分旧实例(未覆盖同名属性)都能访问
- 示例:
function Animal() {}<br> const dog = new Animal();<br> Animal.prototype.speak = function() { return 'woof'; };<br> console.log(dog.speak()); // 'woof'(只要dog没自己定义speak)
慎用 __proto__ 直接赋值
obj.__proto__ = newProto虽能立即生效,但存在明显问题:
- 非标准属性(尽管主流引擎支持),已被ECMAScript列为遗留特性
- 可能触发引擎内部原型链重缓存,影响性能
- 在严格模式下对不可扩展对象赋值会抛
TypeError - 建议仅用于调试或非常规场景,生产代码优先选
Object.setPrototypeOf()
挂载原型时的关键细节
动态挂载不是“万能补丁”,需留意几个实际约束:
- 原型链查找只发生在读取属性时,挂载前已缓存的访问结果(如闭包中保存的函数引用)不会自动更新
- 若目标对象自身已有同名属性,原型上的同名方法/属性将被屏蔽(遮蔽),挂载后也无效
- 避免频繁切换原型——这会干扰V8等引擎的内联缓存(IC),导致性能下降
- 想让多个对象共享同一套行为?考虑用
Object.create(proto)创建新对象,而非改造旧对象原型
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











