JavaScript中数组内对象属性值无法修改的技术问题咨询
嘿,我看了你的代码和遇到的问题,这俩常见的JS引用类型坑我之前也踩过,给你拆解下问题根源和修复方案:
为啥数组内对象属性改不动?
先看你构造函数里的this.configurationState=[]——这个数组一开始是空的对吧?如果你的第一个循环直接去修改this.configurationState[i].parameterValue,那this.configurationState[i]其实是undefined,给undefined赋值属性当然不会生效,甚至会抛出Cannot set properties of undefined的错误。
解决办法很简单:先给数组每个位置创建对象,再去修改属性。比如初始化的时候:
// 示例:根据需求初始化数组元素为带默认属性的对象 for(var i=0; i<你需要的长度; i++){ this.configurationState[i] = { parameterValue: 0 }; }
如果你的配置长度和传入的data有关,也可以在setData里做这个初始化,比如:
this.setData = function(data){ this.data = data; // 用data的长度初始化配置数组 this.configurationState = data.map(() => ({ parameterValue: 0 })); };
另一个隐形坑:PSTrail存的都是同一个状态
看你循环里直接this.PSTrail.push(this.configurationState)——数组是引用类型,你每次push的都是同一个数组的地址,后续修改configurationState的元素时,PSTrail里的所有条目都会跟着变,最后打印出来全是最后一次的状态,这肯定不是你想要的。
要存每次修改后的独立状态,得拷贝当前数组和里面的对象:
for(var i=0; i<this.configurationState.length; i++){ this.configurationState[i].parameterValue = i * 5; // 示例:和i相关的数值 // 浅拷贝数组+每个对象,确保每次存的是独立快照 const currentStateSnapshot = this.configurationState.map(item => ({...item})); this.PSTrail.push(currentStateSnapshot); }
如果你的对象嵌套更深(比如parameterValue里还有子对象),那得用深拷贝,简单点可以用JSON.parse(JSON.stringify(item))(注意这个方法不能处理函数、Symbol这类特殊值),或者自己写递归拷贝函数。
修复后的完整示例代码
把这些问题都修好后,你的类大概是这样的(顺便把构造函数首字母大写了,这是JS的通用惯例,方便区分构造函数和普通函数):
function ConfigurationToken(){ this.setData = function(data){ this.data = data; // 初始化配置数组,每个元素是带默认属性的对象 this.configurationState = data.map(() => ({ parameterValue: 0 })); }; this.configurationState = []; this.PSTrail = []; // 别忘了初始化追踪数组 this.analyse = function(){ // 先确保配置数组已经初始化 if(this.configurationState.length === 0 && this.data){ this.configurationState = this.data.map(() => ({ parameterValue: 0 })); } // 循环修改状态并追踪 for(var i=0; i<this.configurationState.length; i++){ this.configurationState[i].parameterValue = i * 10; // 替换成你的业务逻辑数值 // 生成当前状态的快照存入PSTrail const stateSnapshot = this.configurationState.map(item => ({...item})); this.PSTrail.push(stateSnapshot); } // 输出最终的追踪数组 console.log(this.PSTrail); }; }
最后提个小建议
JS里构造函数首字母大写是通用规范,比如ConfigurationToken而不是configurationToken,这样别人看代码的时候一眼就能认出这是用来new实例的构造函数,可读性会好很多~
内容的提问来源于stack exchange,提问作者P.W

