原型属性变更能立刻影响已存在的实例,前提是实例未定义同名属性遮蔽原型;这是JavaScript原型链动态查找机制所致,与Vue/React响应式在原理、目的和实现上完全不同。

原型属性变更能立刻影响已存在的实例,但前提是实例自身没有同名属性遮蔽原型。这不是响应式框架的特性,而是 JavaScript 原型机制的自然行为;它和 Vue、React 等框架的“响应式”在原理、目的和实现上完全不同——前者是语言级的属性查找机制,后者是为视图更新服务的数据监听系统。
原型链查找让修改“实时可见”
每个实例对象都通过 __proto__ 指向其构造函数的 prototype。属性访问时,JS 引擎每次都会按顺序查找:
- 先检查实例自身是否拥有该属性(hasOwnProperty)
- 没有则顺着 __proto__ 到原型对象上找
- 原型上也没有,继续向上直到 null
这个过程不缓存结果,也不复制值。所以只要原型上的属性被添加、修改或删除,下一次读取就会拿到新值或 undefined。
哪些操作真正生效
只有对**原有原型对象本身**的操作才会影响已有实例:
- 添加属性:Person.prototype.city = '杭州' → 所有未设置 city 的实例立即可读到 '杭州'
- 修改属性:Person.prototype.age = 25 → 已存在且未覆盖 age 的实例读取结果变为 25
- 删除属性:delete Person.prototype.age → 实例再次读取时会继续向上查找,可能返回继承链更上层的值或 undefined
但以下操作不会影响已创建的实例:
- 用 Person.prototype = { ... } 彻底替换原型对象 → 已有实例仍指向旧原型
- 实例自身设置了同名属性(如 obj.age = 30)→ 后续读取始终走自身,不再访问原型
和框架响应式不是一回事
Vue 或 React 的响应式关注的是“数据变 → 视图自动更新”,依赖 Proxy/Object.defineProperty 劫持读写、收集依赖、触发更新。而原型属性变更只是改变了属性查找路径,它本身不触发任何副作用函数、不通知组件重渲染、也不管理依赖关系。
- Vue 3 用 Proxy 代理整个对象,支持新增/删除属性、数组索引变化,还能嵌套递进代理
- 原型机制没有“依赖收集”概念,也不存在“派发更新”,更不涉及 effect、watch 或 render 函数的重新执行
- 如果你希望某个计算值(如 sum = a + b)随 a/b 变化自动更新,必须借助响应式 API(ref、computed、effect),不能只靠原型赋值
实际开发中容易混淆的点
有人试图用修改原型的方式实现“全局状态响应”,比如给 Object.prototype 添加方法或属性。这不仅污染原生原型,而且无法触发视图更新——因为模板里 {{ obj.name }} 的读取虽然会走到原型,但 Vue 并没有为此建立响应联系。
- 想让页面响应变化,请用 ref()、reactive() 或 computed()
- 想复用逻辑,请用 mixins(Vue2)、composables(Vue3)或普通函数,而不是往原型上挂东西
- 调试时发现属性没更新?先确认是不是实例自身已定义同名属性,再检查是否误替换了整个 prototype

















