运行 设置深度 属性 时的函数
Run a function when deep property is set
我有一个像
这样的对象
const obj = { field1: obj1, field2: obj2 }
现在我想 运行 当 obj
中的任何内容发生更改时的函数:
function objChanged() { ... }
// decorate obj somehow ...
obj.field3 = data; // objChanged should be called (Proxy can see it)
obj.field1.val = data; //objChanged should be called (Proxy can't see it?)
据我所知,有一个 MutationObserver which works only for DOM and Proxy 只拦截自己的属性,对吧?
我不拥有 obj1
所以我无法更改它。有没有办法实现这个功能?
下面的代码片段将监听对象 属性 您可以遍历对象属性以监听所有对象。我很好奇,你想达到什么目的?
const dog = { bark: true };
function Observer(o, property) {
var _this = this;
this.observers = [];
this.Observe = function (notifyCallback) {
_this.observers.push(notifyCallback);
};
Object.defineProperty(o, property, {
set: function (val) {
_this.value = val;
for (var i = 0; i < _this.observers.length; i++) {
_this.observers[i](val);
}
},
get: function () {
return _this.value;
},
});
}
const observer = new Observer(dog, "bark");
observer.Observe(function (value) {
l("Barked");
});
dog.bark = true;
dog.bark = true;
dog.bark = true;
dog.bark = true;
Orgil 的答案仅适用于需要知道和编码的单个 属性。我想要一个适用于所有属性的解决方案,包括后来添加的。受他创建观察对象的想法的启发,我创建了一个动态代理,可以在需要时添加另一个代理。
在以下代码中,dog1
用作代理:设置其属性会修改原始 dog
对象并将分配的值记录到控制台。
function AssignProxy(o, fn, path) {
var tree = {};
if(!path) path = "obj";
return new Proxy(o, {
get: (_, prop) => {
if(typeof o[prop] != "object") return o[prop];
if(tree[prop] === undefined) tree[prop] = AssignProxy(o[prop], fn, `${path}.${prop}`);
return tree[prop];
},
set: (_, prop, val) => fn(o[prop] = val, prop, o, path) || 1
});
}
/****** TEST *******/
const dog = {
sounds: {},
name: "Spike"
};
let callback = (val, prop, o, path) => console.log(`assigning ${path}.${prop} to ${val}`)
const dog1 = AssignProxy(dog, callback, "dog1");
dog1.name = "Tyke"; // overwrite property
dog1.age = 4; // create a property
dog1.sounds.howl = "hoooooowl"; // create a deep property
dog1.sounds.howl = {text: "hoowl", pitch: 5000}; // overwrite the deep property
var howl = dog1.sounds.howl; // access by reference
howl.pitch = 6000; // overwrite later added property
console.log(dog); // verify the original object
我有一个像
这样的对象const obj = { field1: obj1, field2: obj2 }
现在我想 运行 当 obj
中的任何内容发生更改时的函数:
function objChanged() { ... }
// decorate obj somehow ...
obj.field3 = data; // objChanged should be called (Proxy can see it)
obj.field1.val = data; //objChanged should be called (Proxy can't see it?)
据我所知,有一个 MutationObserver which works only for DOM and Proxy 只拦截自己的属性,对吧?
我不拥有 obj1
所以我无法更改它。有没有办法实现这个功能?
下面的代码片段将监听对象 属性 您可以遍历对象属性以监听所有对象。我很好奇,你想达到什么目的?
const dog = { bark: true };
function Observer(o, property) {
var _this = this;
this.observers = [];
this.Observe = function (notifyCallback) {
_this.observers.push(notifyCallback);
};
Object.defineProperty(o, property, {
set: function (val) {
_this.value = val;
for (var i = 0; i < _this.observers.length; i++) {
_this.observers[i](val);
}
},
get: function () {
return _this.value;
},
});
}
const observer = new Observer(dog, "bark");
observer.Observe(function (value) {
l("Barked");
});
dog.bark = true;
dog.bark = true;
dog.bark = true;
dog.bark = true;
Orgil 的答案仅适用于需要知道和编码的单个 属性。我想要一个适用于所有属性的解决方案,包括后来添加的。受他创建观察对象的想法的启发,我创建了一个动态代理,可以在需要时添加另一个代理。
在以下代码中,dog1
用作代理:设置其属性会修改原始 dog
对象并将分配的值记录到控制台。
function AssignProxy(o, fn, path) {
var tree = {};
if(!path) path = "obj";
return new Proxy(o, {
get: (_, prop) => {
if(typeof o[prop] != "object") return o[prop];
if(tree[prop] === undefined) tree[prop] = AssignProxy(o[prop], fn, `${path}.${prop}`);
return tree[prop];
},
set: (_, prop, val) => fn(o[prop] = val, prop, o, path) || 1
});
}
/****** TEST *******/
const dog = {
sounds: {},
name: "Spike"
};
let callback = (val, prop, o, path) => console.log(`assigning ${path}.${prop} to ${val}`)
const dog1 = AssignProxy(dog, callback, "dog1");
dog1.name = "Tyke"; // overwrite property
dog1.age = 4; // create a property
dog1.sounds.howl = "hoooooowl"; // create a deep property
dog1.sounds.howl = {text: "hoowl", pitch: 5000}; // overwrite the deep property
var howl = dog1.sounds.howl; // access by reference
howl.pitch = 6000; // overwrite later added property
console.log(dog); // verify the original object