web-interview
web-interview copied to clipboard
[vue] 4. 为什么要替换 Object.defineProperty?
答案:
在 Vue 中,Object.defineProperty 无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。
Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。
其实通过下标给数组设置,是可以触发set方法的,但是像push、shift、unshift等操作数组并不会触发get方法,以下是测试代码
` function myDefineProperty(data, key, value) { Object.defineProperty(data, key, { configurable: true, get: () => { console.log("get", "key:", key); console.log("get", "value:", value); return value; }, set: (newValue) => { console.log("set", "key:", key); console.log("set", "value:", value); console.log("set", "newValue:", newValue); value = newValue; }
})
}
function observe(data) {
Object.keys(data).forEach((key) => {
myDefineProperty(data, key, data[key])
})
}
let arr = ['哈哈', '哦哦', '噢噢'];
observe(arr);
//通过下标获取数组会触发get方法
// console.log(arr[0]);
//通过下标更改数组的值触发set方法
// arr[0] = '呵呵';
//通过push增加数组元素,并不能触发get和set方法
// arr.push("嘻嘻");
//通过unshift添加数组元素,会导致索引重置,
//也就是说将所以元素取出来,然后将unshift参数添加到数组中,然后将原来的数组添加到数组,
//这时候会导致每次添加会触发set方法、get方法(会执行4次)
// arr.unshift("可可");
// console.info(arr[arr.length - 1]);//不会触发get方法,这是因为原数组索引为0,1,2的执行了observe,unshift相当于新增了索引,这时候需要手动observe
//通过pop删除数组元素,会触发get方法
// arr.pop();
//删除数组首个元素,会导致数组索引发生变化,会触发set和get方法,最后一个元素需要手动observe(同unshift)
// arr.shift();
//从索引为1的位置开始,删除0个元素,并插入"测试"元素,
//会导致索引发生变化,最后一个元素需要手动observe(同unshift)
// arr.splice(1, 0, "测试");
`