javascript原型链具有动态性:修改构造函数的prototype对象后,所有新旧实例立即共享新增成员,因实例通过__proto__实时委托查找;但不可替换整个prototype,且需避免污染原生原型。

JavaScript 中原型链的动态性意味着:只要修改构造函数的 prototype 对象,所有已存在和将创建的实例都能立即访问新增的属性或方法——因为实例本身不存储这些成员,而是通过 __proto__ 链向上委托查找。
原型对象被所有实例共享
每个函数(包括构造函数)都有一个 prototype 属性,它是一个普通对象,默认带有一个 constructor 指回该函数。所有通过 new 创建的实例,其内部 [[Prototype]](即 __proto__)都指向该构造函数的 prototype。这个链接不是快照,而是实时引用。
- 修改
Person.prototype.sayHi = function() { console.log('Hi!'); };后,之前创建的p1、p2和之后新建的p3都能立刻调用p1.sayHi() - 即使实例已经存在多年,只要原型链未被切断(比如没手动覆盖
p1.__proto__),它就始终能响应原型上的变更
新增方法/属性立即生效
向原型添加新成员,相当于为整个“家族”统一升级能力,无需遍历或重实例化。
-
注意:必须直接赋值给
Constructor.prototype,而不是替换整个prototype对象(否则会断开已有实例的__proto__连接) - 正确:
Array.prototype.last = function() { return this[this.length - 1]; };→ 所有数组实例立刻获得[1,2,3].last() - 错误:
Array.prototype = { last: ... };→ 已有数组无法访问,仅对后续new Array()生效(且破坏原生行为)
运行时补丁与兼容性增强
这是 polyfill 的核心原理:检测缺失方法,只在需要时向原型注入实现。
- 例如为旧浏览器补全
String.prototype.includes:if (!String.prototype.includes) { String.prototype.includes = function(search) { return this.indexOf(search) !== -1; }; } - 执行后,所有已存在的字符串(如
const s = "hello";)立刻拥有s.includes('e')能力 - 这种“热插拔”能力是 JavaScript 动态本质的直接体现,也是框架(如 Vue 2 的响应式代理前缀方法)早期扩展的基础
限制与注意事项
动态添加虽强大,但需谨慎使用:
- 避免污染原生原型(尤其团队项目),可能引发冲突或意外覆盖;优先考虑工具函数或 class 继承
- 不能通过原型添加私有数据(如闭包变量),因为所有实例共享同一原型对象,数据会互相干扰
- 若实例自身已有同名属性(如
p1.sayHi = ...),则会屏蔽原型上的同名方法(遮蔽效应),此时修改原型不影响该实例
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











