JavaScript修改对象单个属性时同类属性同步更新问题
问题产生原因
这个现象是JavaScript的引用类型赋值特性导致的:
- 你在循环外部定义了
endtime、running、time_left三个数组,数组属于引用类型,变量中存储的不是数组本身的内容,而是数组在内存中的存储地址。 - 循环给
timer下不同key(即delayed_output_timer和startup_timer)赋值属性时,你只是把这三个数组的内存地址传给了两个对象的对应属性,两个对象的endtime/running/time_left指向的是内存里完全相同的三个数组,没有生成独立的副本。 - 这种情况下不管你通过哪个对象修改数组里的元素,本质都是修改公共数组的内容,另一个对象读取同一个数组自然会拿到修改后的值,和你用点语法还是方括号语法访问属性没有任何关系。
修复方案
不需要改动整体结构,只要把三个数组的定义移到遍历types的循环内部即可,保证每次处理不同计时器类型时,都创建全新的独立数组,不同对象的属性指向各自独立的内存空间,修改就不会互相影响。
修正后的核心代码如下:
n_machines = global.get("n_machines"); types = ["delayed_output_timer","startup_timer"]; timer = {}; for(i = 0 ; i < types.length ; i++){ let key = types[i]; // 每次循环都创建全新的独立数组,不复用外部数组 let endtime = []; let running = []; let time_left = []; // 给当前计时器类型初始化默认值 for(m_num = 0; m_num < n_machines; m_num ++) { endtime[m_num] = 0; running[m_num] = false; time_left[m_num] = 0; } timer[key] = { endtime: endtime, running : running, time_left : time_left }; } timer.delayed_output_timer.running[0] = "TESTING"; let test = timer['delayed_output_timer'].running[0]; msg = {payload:[timer,test],topic:"timer"}; return msg;
补充:如果你后续需要在其他场景复用已有数组、又不希望引用联动,也可以用浅拷贝生成新数组,比如
let newRunning = [...oldRunning],但当前场景下直接在循环内新建数组是最简洁高效的方案。
内容的提问来源于stack exchange,提问作者Rene De ren
相关产品推荐
相关产品推荐

