一、 对象的深拷贝
1. 简单深拷贝获取对象
/**
* 简单深拷贝获取对象
* @param data
* @returns
*/
export function dataCopy(data: any) {
return JSON.parse(JSON.stringify(data))
}
2. 复杂深拷贝获取对象,包含函数深拷贝
/**
* 复杂深拷贝获取对象,包含函数深拷贝
* @param data
* @returns
*/
export function dataCopyFn(data: any) {
return Object.create(data)
}
二、forEach循环回调中push数组(只push最后一个元素的解决方案)
以下是针对push字符串类型的元素的代码案例介绍:
先记录下踩坑之路:
这种push([…arr]) 的方式会使控制台如下报错:
nonIterableSpread.js:2 Uncaught (in promise) TypeError: Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a Symbol.iterator method.
解决方案:使用普通的数组拼接
this.arrStringDetail.concat(callData);
arr.forEach((item) => {
// 回调函数
const isStringCall = (callData) => {
console.log('isStringCall===', callData);
if (callData) {
// 全局定义的数组 this.arrStringDetail, 采用[...]的写法,解决只push最后一个元素,这里是关键
// this.arrStringDetail.push([...callData]); 踩坑: 这种方式会报错
this.arrStringDetail.concat(callData);
console.log('this.arrStringDetail=====', this.arrStringDetail);
}
};
// 这是一个搜索调用后端接口的一个函数,此处在循环遍历中调用接口,这个函数有四个传参,可忽略,最后一个传参为回调函数
this.keyFieldsSearch(item, _, true, isStringCall);
});
// 这是搜索调用后端接口的一个函数,对应上面的四个传值
private keyFieldsSearch(
query: string,
isCreated: boolean = true,
isStringMsg?: boolean = false,
resCall?: any
) {
// 此处省略调用后端接口的方法
// ...
// 在回调中传入 参数,resCall为传入的回调函数
if (isStringMsg) {
// 过滤方法
const filterObjData = this.keyFieldsData.filter(
(item: KeyFieldsItemType) => item.copyName === query
);
if (!filterObjData.length) {
return;
}
if (!resCall) {
return;
}
// 主要用到这一步
resCall(filterObjData[0]);
}
}
备注:
- 如果数组是一维数组,而且里边都是基本元素(比如:字符串、数字),那么拷贝后的数组和原来数组数据是相互独立的,修改其中一个数组不会影响原来数组。
- 如果数组是二维数组或者是对象数组,那么拷贝后的数组和原来数组数据不是相互独立的,修改其中一个数组会影响原来数组。
更多浅拷贝案例,请参考numbers = [1, 2, 3]; numbersCopy = [...numbers];
三、取二维数组中每一项的最后一个值
/**
* 取二维数组中每一项的最后一个值
*/
export const getDoubleArrayVal = (arr: any[]): any[] => {
return arr.map((item: any[]) => item[item.length - 1])
}