1,对象监听
let obj = {
a: {
b: 1,
c: 2,
},
d: 4,
};
observe(obj);
obj.a.b = 3; //直接修改b的值 监听成功
obj.a = 4; //把a赋值成基本类型 监听成功
obj.d = 5; //直接修改d的值 监听成功
obj.d = {
//把d修改成对象 监听成功
e: 8,
};
console.log(obj.d);
//对对象进行观测
function observe(target) {
if (typeof target !== "object" || target === null) {
return target;
}
//如果target为数组则改变原型指向,使用重写后的方法
if (Array.isArray(target)) {
target.__proto__ = arrProto;
}
//遍历每一个属性,进行监听
for (let key in target) {
defineProperty(target, key, target[key]);
}
}
//监听函数
function defineProperty(target, key, value) {
//当value也为对象时进行递归深度监听
observe(value);
Object.defineProperty(target, key, {
get() {
return value; //依赖收集
},
set(newValue) {
if (newValue !== value) {
update(value, newValue); //通知相关依赖进行更新
value = newValue;
//当新值赋值为对象时, 对该对象进行监听
observe(newValue);
}
},
});
}
function update(oldValue, newValue) {
console.log(`oldValue: ${oldValue}, newValue: ${newValue}`);
}
2,数据响应式数组方法重写
let arrPrototype = Array.prototype;
// 该方法创建新对象,隐式原型原型指向arrPrototype,扩展新的方法时不会影响原型
const arrProto = Object.create(arrPrototype);
//重写方法的返回值
["push", "pop", "shift", "unshift", "splice", "sort", "reverse"].forEach(
(methodName) => {
// 缓冲原始数组的方法
var original = arrayProto[method];
// 利用Object.defineProperty对方法的执行进行改写
def(arrayMethods, method, function mutator(val) {
var args = [],
len = arguments.length;
while (len--) args[len] = arguments[len];
// 执行原数组方法
var result = original.apply(this, args);
// 新增数组的方法push,unshift,splice可以帮我们更新数组中的新增一项
var inserted;
switch (method) {
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
break;
}
//在此处进行通知
return result;
});
}
);
//进行监听
function def(obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true,
});
}
本文探讨了JavaScript中对象监听技术,如Observe函数实现的深度监听,并着重介绍了如何重写数组方法以实现实时数据响应。通过观察对象属性变化和数组操作,展示了如何在对象和数组的修改中保持数据同步。
455

被折叠的 条评论
为什么被折叠?



