1、对象合并
export function mergeObject(...objs){
//声明一个空对象
const result = {};
//遍历所有的参数对象
objs.forEach(obj => {
//获取当前对象所有的属性
Object.keys(obj).forEach(key => {
//检测 result 中是否存在 key 属性
if(result.hasOwnProperty(key)){
result[key] = [].concat(result[key], obj[key]);
}else{
//如果没有 则直接写入
result[key] = obj[key];
}
});
});
return result;
}
<script>
const object = {
a: [{ x: 2 }, { y: 4 }],
b: 1,
}
const other = {
a: { z: 3 },
b: [2, 3],
c: 'foo'
}
console.log(mergeObject(object, other))
result:{ a:[ {x:2} , {y:4} , {z:3} ], b:[1,2,3], c:'foo' ]
</script>
2、浅拷贝
浅拷贝:只是复制了对象属性或数组元素本身(只是引用地址值)。修改一个会另一个也会改变
深拷贝:不仅复制了对象属性或者数组元素本身,还复制了指向的对象(使用递归)。每个对象都是一个新的
浅拷贝:
/**
*
* @param {*} target
*/
export function clone1(target){
//类型判断 {} [] null
if(typeof target === 'object' && target !== null){
//判断数据是否为数组
if(Array.isArray(target)){
return [...target];
}else{
return {...target};
}
}else{
return target;
}
}
/**
*
* @param {*} target
*/
export function clone2(target){
//判断
if(typeof target === 'object' && target !== null){
//创建一个容器
const result = Array.isArray(target) ? [] : {};
//遍历 target 数据
for(let key in target) {
//判断当前对象身上是否包含该属性
if(target.hasOwnProperty(key)){
//将属性设置到 result 结果数据中
result[key] = target[key];
}
}
return result;
}else{
return target;
}
}
深拷贝:
deepClone1存在问题:存在一个函数方法关系不能拷贝、属性循环引用不支持
export function deepClone1(target){
//通过数据创建 JSON 格式的字符串
let str = JSON.stringify(target);
//将 JSON 字符串创建为 JS 数据
let data = JSON.parse(str);
return data;
}
deepClone2存在问题:属性循环引用不支持
export function deepClone2(target){
//检测数据的类型
if(typeof target === 'object' && target !== null ){
//创建一个容器
const result = Array.isArray(target) ? [] : {};
//遍历对象
for(let key in target){
//检测该属性是否为对象本身的属性(不能拷贝原型对象的属性)
if(target.hasOwnProperty(key)){
//拷贝
result[key] = deepClone2(target[key]);
}
}
return result;
}else{
return target;
}
}
deepClone:解决上面两种存在的问题,循环引用主要通过创建一个map进行对上个克隆的属性进行缓存处理。
export function deepClone3(target, map=new Map()){
//检测数据的类型
if(typeof target === 'object' && target !== null ){
//克隆数据之前, 进行判断, 数据之前是否克隆过
let cache = map.get(target);
if(cache){
return cache;
}
//创建一个容器
const result = Array.isArray(target) ? [] : {};
//将新的结果存入到容器中
map.set(target, result);
//遍历对象
for(let key in target){
//检测该属性是否为对象本身的属性(不能拷贝原型对象的属性)
if(target.hasOwnProperty(key)){
//拷贝
result[key] = deepClone3(target[key], map);
}
}
return result;
}else{
return target;
}
}
deepClone4:最优化的代码
export function deepClone4(target, map=new Map()){
//检测数据的类型
if(typeof target === 'object' && target !== null ){
//克隆数据之前, 进行判断, 数据之前是否克隆过
let cache = map.get(target);
if(cache){
return cache;
}
//判断目标数据的类型
let isArray = Array.isArray(target);
//创建一个容器
const result = isArray ? [] : {};
//将新的结果存入到容器中
map.set(target, result);
//如果目标数据为数组
if(isArray){
//forEach 遍历
target.forEach((item, index) => {
result[index] = deepClone4(item, map);
});
}else{
//如果是对象, 获取所有的键名, 然后 forEach 遍历
Object.keys(target).forEach(key => {
result[key] = deepClone4(target[key], map);
});
}
return result;
}else{
return target;
}
}