深拷贝和浅拷贝的区别

深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。
深拷贝:
深拷贝复制变量值,对于非基本类型变量,则递归至基本类型变量后,再复制。深拷贝后的对象与原来的对象是完全隔离的,并不互相影响,对一个对象的修改并不会影响另一个对象。
浅拷贝:
浅拷贝是会将对象的每个属性进行依次复制。但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时,也会随着改变。
可以使用for in , object.assign, 扩展运算符...,Array.prototype.slice(),Array.prototype.concat()等,例如:

let obj = {
        name: 'sam',
        age: 19,
        hobbies: ['reading', 'photography']
    }
     let obj2 = Objcet.assign({}, obj);
let obj3 = {...obj };
obj.name = 'jack';
obj.hobbies.push('coding');
console.log(obj); //{name: "jack", age: 19, hobbies: ["reading", "photography", "coding"]}
console.log(obj2); //{name: "sam", age: 19, hobbies: ["reading", "photography", "coding"]}
console.log(obj3); //{name: "sam", age: 19, hobbies: ["reading", "photography", "coding"]}

可以看出浅拷贝只对第一层的属性进行拷贝,当第一层的属性值是基本数据类型时,新的对象和原来的对象互不影响。但是如果第一层的属性是复杂数据类型,那么新对象和原有对象的属性值其指向的是同一块内存地址。

深拷贝实现:
深拷贝最简单的实现是:JSON.parse(JSON.stringify(obj));
但有一些缺陷:
1对象的属性值是函数无法拷贝,
2原型链上的属性无法拷贝
3不能正确处理date类型的数据
4不能处理RegExp
5会忽略symbol
6会忽略undefined

deepClone函数
1如果是基本数据类型,直接返回,
2如果是RegExp或者Date类型,返回对应类型
3如果是复杂数据类型,递归
4考虑循环引用问题

function deepClone(obj, hash = new WeakMap()) { //递归拷贝
    if (obj instanceof RegExp) return new RegExp(obj);
    if (obj instanceof Date) return new Date(obj);
    if (obj === null || typeof obj !== 'object') {
        //如果不是复杂数据类型,直接返回
        return obj;
    }
    if (hash.has(obj)) {
        return hash.get(obj);
    }
    //如果obj是数组,那么obj.constructor 是[Function:Array]
    //如果obj是对象,那么obj.constructor 是[Function:Object]
    let t = new obj.constructor();
    hash.set(obj, t);
    for (let key in obj) {
        //递归
        if (obj.hasOwnProperty(key)) { //是否是自身的属性
            t[key] = deepClone(obj[key], hash);

        }
    }
    return t
}
export function deepClone(source) {
  if (!source && typeof source !== "object") {
    throw new Error("error arguments", "shallowClone");
  }
  const targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach(keys => {
    if (source[keys] && typeof source[keys] === "object") {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });
  return targetObj;
}

export function uniqueArr(arr) {
  return Array.from(new Set(arr));
}

export function isExternal(path) {
  return /^(https?:|mailto:|tel:)/.test(path);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容