- Object.defineProperty:JS 用来“在对象某个属性上定义 getter/setter”的底层 API。Vue2 用它把每个字段变成“被访问会收集依赖、被修改会触发更新”。
1.拦截范围
defineProperty:只能拦截某个已存在属性的 get/set
2.新增/删除属性
defineProperty(Vue2):新增/删除属性默认监听不到(所以有 Vue.set / this.$set、Vue.delete)
3.数组响应式
defineProperty(Vue2):对数组要做很多“方法重写/补丁”(push/pop/splice 等)来触发更新;直接改索引曾经是坑点之一
4.性能与实现复杂度
defineProperty:需要递归把每个属性都“改造成 getter/setter”,对象大时初始化成本高
5.兼容性
defineProperty:兼容更老的浏览器(Vue2 能支持 IE)
小案例:新增属性这一点最直观:
// defineProperty 拦不到“后来新增的 key”(Vue2 时代需要 Vue.set)
const obj = {}
obj.a = 1 // 这一步如果没提前 defineProperty,是无法自动变成响应式的