Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 修改对象属性时如何触发回调?_Javascript_Class_Ecmascript 6_Callback - Fatal编程技术网

Javascript 修改对象属性时如何触发回调?

Javascript 修改对象属性时如何触发回调?,javascript,class,ecmascript-6,callback,Javascript,Class,Ecmascript 6,Callback,如果我有一门课,比如: class Myclass { constructor(){ this.a = []; this.sum = 0; } update(){ this.sum = this.a.reduce((a, b) => a + b, 0) } } 我实例化这个类: myClass = new Myclass(); 我将一个数字附加到a属性 myClass.a.push(1); myClass.

如果我有一门课,比如:

class Myclass {
    constructor(){
        this.a = [];
        this.sum = 0;
    }

    update(){
       this.sum = this.a.reduce((a, b) => a + b, 0)
    }
}
我实例化这个类:

myClass = new Myclass();
我将一个数字附加到
a
属性

myClass.a.push(1);
myClass.a.push(2);

如何在每次修改
属性时调用update方法?换句话说,当对象属性被更改时,如何触发回调?

可以将对象组织为

class Myclass {
    constructor(){
        this.a = [];
    }

    get sum(){
       return this.a.reduce((a, b) => a + b, 0)
    }
}

如果我没有弄错,调用
myClass.sum
将返回数组中
a
属性下保存的值的总和。

添加将新项推送到
a
数组的方法,例如:

class Myclass {
    constructor(){
        this.a = [];
        this.sum = 0;
    }

    update(){
       this.sum = this.a.reduce((a, b) => a + b, 0)
    }

    pushItem(val) {
        this.a.push(val);
        this.update();
    }

}

myClass = new Myclass();
myClass.pushItem(1);
myClass.pushItem(2);
console.log(myClass.sum);
换句话说,当对象属性被更改时,如何触发回调

这是对上述问题的一般解决办法。如果您只需要
a
阵列的特定于用例的解决方案,请忽略此问题

检查是否有比简单的getter/setter更强大的get/set拦截功能。由于您有嵌套的数据结构,因此可能需要递归地使用代理进行包装。大概是这样的:

函数wrapWithProxyCallback(obj,回调){
返回新代理(obj{
获取(目标、键、接收器){
const result=Reflect.get(目标、键、接收器)
//使用代理包装嵌套数据
if(typeof result=='object'&&result!==null){
返回wrapWithProxyCallback(结果,回调)
}
返回结果
},
设置(目标、键、值、接收器){
//对每个集合操作调用回调
回调(目标、键、值/*以及您需要的任何内容*/)
返回Reflect.set(目标、键、值、接收者)
}
})
}
然后像这样使用它:

const wrappedClass=wrapWithCallback(
我的班级,
(target,key)=>console.log(target[key])
)
//这将调用上述回调
包装类a.push(1);
这有点幼稚,但却是一个很好的起点。例如,您可能需要检查嵌套数据是否已由代理包装

您想要做的可能是很好地与透明的反应性保持一致(不过我必须查看回调的内容才能确定这一点)。我认为您应该检查mobx或@nx js/observer util(后者由我编写)以获得生产就绪的盒装解决方案


编辑:我的第一个示例在get操作时触发回调,我将其更正为在set操作时触发。

一种方法是扩展
Array
并隐藏
push
方法

类MyArray扩展了数组{
建造师(参考){
超级();
this.ref=ref
}
推送(值){
超级推送(值)
this.ref.update()
console.log(“被调用”)
}
}
类Myclass{
构造函数(){
this.a=新的MyArray(this);
此值为0.sum=0;
}
更新(){
this.sum=this.a.reduce((a,b)=>a+b,0)
}
}
让myClass=新建myClass()
myClass.a.push(1);
myClass.a.push(2);

console.log(myClass.sum)
一般来说,您可以使用getter/setter来实现此目的,但是
.a
属性没有改变,没有分配给它。相反,属性所持有的数组是变异的,而检测它则要复杂一些。