深浅拷贝
~如果你的目的是仅仅更新 this.ruleForm
中与 res.data
中相同键的值,而不添加新属性也不移除未出现在 res.data
中的原有属性
1.{...data}
this.ruleForm = {...res.data}
的方式实际上是使用扩展运算符(spread operator)进行了浅拷贝,这意味着如果 res.data
中包含了 this.ruleForm
原本不存在的属性,这些新属性也会被添加到 this.ruleForm
中,从而改变了 this.ruleForm
的结构。同时,如果 res.data
中某些属性的值为 undefined
或者未定义,这也会直接覆盖掉 this.ruleForm
中对应的属性值,即便你可能并不希望这样做。
~如果您希望将 res.data
中的值赋给 this.ruleForm
,同时保持 this.ruleForm
原有的参数结构不变(即使 res.data
中存在 this.ruleForm
中没有的额外属性),并且不覆盖 this.ruleForm
中已存在的属性,可以采取以下策略:
2.浅拷贝并合并
手动遍历 res.data
的属性,并逐一赋值给 this.ruleForm
。这种方式适合于 res.data
结构较为简单的情况.
for (let key in res.data) {
if (res.data.hasOwnProperty(key)) {
// 确保这个属性在ruleForm中已经存在,避免添加新的属性
if (this.ruleForm.hasOwnProperty(key)) {
this.ruleForm[key] = res.data[key];
}
}
}
3.深拷贝并选择性合并:使用深度拷贝方法(如 JSON.parse(JSON.stringify())
,但注意这种方法对于函数和循环引用的对象不适用)创建 res.data
的副本,然后根据需要合并到 this.ruleForm
。这种方式适用于需要更精细控制合并过程的情况
let newData = JSON.parse(JSON.stringify(res.data)); // 深拷贝res.data
for (let key in newData) {
if (newData.hasOwnProperty(key) && this.ruleForm.hasOwnProperty(key)) {
this.ruleForm[key] = newData[key];
}
}
补一点循环:
遍历数组:
1.forEach
方法(本身不返回任何值(返回值是undefined
))直接在原数组上进行操作,并不会返回一个新的数组或值,而是通过回调函数处理数组的每个元素
2.map:
于原数组创建一个新数组并赋值
parmas.t0154XlyjlxqtjglMxList = this.ruleForm.dynamic.map((item, iIndex) => {
// 根据需要处理item并返回,例如:
return { ...item, someNewProperty: '新值' };
});
3.普通的for
4.for...of循环: 用于遍历可迭代对象(包括数组、Set、Map等)
for(const item of array) {
console.log(item); }
5.filter(): 创建一个新数组,包含通过测试的所有元素。
const filteredArray = array.filter(item => item > 10);
6.reduce() / reduceRight(): 对数组中的每个元素执行一个由您提供的reducer函数(升序/reverse),最终累计成一个单一的返回值。
const sum = array.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
7.some(): 检测数组中的元素是否满足测试函数,只要有一个元素满足则返回true。
const hasEven = array.some(item => item % 2 === 0);
8.every(): 检查数组中的所有元素是否都满足测试函数,全部满足才返回true。
const allEven = array.every(item => item % 2 === 0);
9.find() / findIndex(): 返回数组中满足提供的测试函数的第一个元素的值/索引。否则返回undefined/-1。
const foundItem = array.find(item => item.id === 1);
const foundIndex = array.findIndex(item => item.id === 1);
遍历对象:
- for...in循环: 遍历对象自身的和继承的可枚举属性。
for(let prop in obj) { if(obj.hasOwnProperty(prop)) { console.log(prop + ": " + obj[prop]); } }
- Object.keys(): 返回一个包含对象自身可枚举属性名的数组,然后可以遍历这个数组。
Object.keys(obj).forEach(key => { console.log(key + ": " + obj[key]); });
- Object.getOwnPropertyNames(): 返回一个数组,包含对象自身的所有属性(不论是否可枚举)。
Object.getOwnPropertyNames(obj).forEach(key => { console.log(key + ": " + obj[key]); });
- Reflect.ownKeys(): 返回一个数组,包含对象自身的所有键,包括常规键和Symbol键。
Reflect.ownKeys(obj).forEach(key => { console.log(key + ": " + obj[key]); });
- Object.entries(): 返回一个数组的数组,每个子数组是一个键值对,可以用来遍历键和值。
Object.entries(obj).forEach(([key, value]) => { console.log(key + ": " + value); });
- 解构赋值与for...of循环: 结合
Object.entries()
使用,提供了一种简洁的遍历键值对的方式。for(const [key, value] of Object.entries(obj)) { console.log(key + ": " + value); }
补一点对象和map
JavaScript中的对象(Object)和Map是两种不同的数据结构,它们有以下主要区别:
-
键的类型:
- 对象: 键必须是字符串(或Symbol,ES6引入)类型。即使你使用非字符串作为键,它们也会被转换为字符串。
- Map: 键可以是任意值,包括对象,这使得Map更灵活。Map内部使用equals比较键,因此两个对象作为键只有在内容和结构完全相同时才被视为相同。
-
迭代顺序:
- 对象: 在ES2015之前,对象的键的迭代顺序是不确定的,尽管ES2015之后引入了有序性,但这主要是为了保证开发者能预测性地访问新增属性,而不是为了提供稳定的遍历顺序。
- Map: 保留插入键值对的顺序,这意味着遍历Map时会按照插入的顺序返回键值对。
-
大小属性:
- 对象: 对象没有直接获取其大小或元素数量的属性。
- Map: 提供了
.size
属性,可以直接获取Map中键值对的数量。
-
内置方法:
- Map: 提供了更多的内置方法,如
.set(key, value)
、.get(key)
、.has(key)
、.delete(key)
、.clear()
等,专门用于键值对的管理。 - 对象: 虽然也可以通过属性访问器操作键值对,但它没有直接对应于Map的某些方法,如直接获取大小或明确的删除方法。
- Map: 提供了更多的内置方法,如
-
性能:
- 对于小规模数据,两者之间的性能差异通常可以忽略不计。
- 对于大规模数据操作,Map由于其内部实现,可能在某些情况下提供更好的性能,尤其是在频繁的增删操作上。
-
兼容性:
- 对象: 是JavaScript的基本数据结构,所有环境都支持。
- Map: 是ES6引入的,较旧的环境可能不支持,需要polyfill或转译。
总结来说,如果你需要使用非字符串作为键,或者关心键的插入顺序,或者需要直接获取集合大小,那么Map可能是更好的选择。而如果项目需要兼容老版本浏览器或环境,或者键明确为字符串类型,使用对象可能更合适。