JS浅拷贝和深拷贝

125 阅读2分钟

1、数据类型

数据类型分为:基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型(Array、Object)

区别:基本数据类型的值存储在栈内存,引用数据类型存储在堆内存里

深入分析: 因为值类型直接赋值内存比较小,对造成的性能不会有问题,所以可以直接赋值 而引用类型的json可以是上千上万行代码,一般造成内存比较大, 因此也需要将栈和堆严格分离出来,引用类型如果像值类型一样直接存储复制值 会非常占内存、耗时

61fe3d380001113519201080.jpg

2、概念

浅拷贝:拷贝就是复制,就相当于把一个对象中的所有的内容,复制一份给另一个对象, 直接复制,或者说,就是把一个对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用(相互会发生影响)

深拷贝:把堆中的内容复制一份,内容改变不会相互影响。(各自独立的)

通俗点就是,浅拷贝是指对象复制的时候只复制一层;深拷贝是指复制对象的所有层级

3、要弄明白的几个问题

1、浅拷贝和深拷贝的区别

2、浅拷贝实现方式

(1)Object.assign()方法

概念:用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

用法:Object.assign(obj1,obj2):obj1是目标对象,obj2是源对象(后面可以接多个参数),最后返回obj1目标对象 (此方法类似于将对象合并,如果参obj1与obj2的key值相同,obj2的值会覆盖obj1)

        let obj1 ={
            name:'小江',
            sex:'男',
            car:{
                a:"丰田"
            }
        }
        let obj2 ={
            name:'小明',
            sex:'女',
            age:23
        }
        let assign = Object.assign(obj1,obj2);
        assign.a = "宝马"
        console.log(assign);  // {name: '小明', sex: '女', car: {a:'丰田'}, age: 23, a: '宝马'}
        console.log(obj1);    // {name: '小明', sex: '女', car: {a:'丰田'}, age: 23, a: '宝马'}

// assign和obj1值是一样的,返回目标对象。

注:Object.assign() 拷贝的是属性值,只实现了对第一层的深拷贝,所以也算是浅拷贝的一种

(2)使用jQuery中的$.extend()

var obj = {
   name: '小江',
   age: 25,
   sex: '男',
   hobby: {
       a: '111'
   }
}

var extend = {}; 
$.extend(extend, obj);     //将obj复制到新对象中
   console.log(extend) //{name: '小江', age: 25, sex: '男', hobby: {a:'111'}};

3、如何手写深拷贝(递归)

    // 定义一串数据
    const obj1 = {
        name: 'zhangsan',
        age: 23,
        city: 'shenzhen',
        arr: ['a', 'b', 'c'],
        object: {
            x: {
                z: 1000
            }
        }
    }
    // 使用深拷贝
    const obj2 = deepLoop(obj1)
    obj2.city = 'beijing'
        console.log(obj1.city); //shenzhen (数据各自独立)
        console.log(obj2.city); //beijing  (数据各自独立)
    
    function deepLoop(obj = {}) {
        //先判断是不是空值 和 是不是对象 , 不是 则返回
        if (typeof obj !== 'object' || obj == null) {
            return obj
        }
        // 定义一个放 存储结果 的空值
        var result
        // 使用 instanceof  来判断obj是否为数组
        if (obj instanceof Array) {
            result = []
        } else {
            result = {}
        }
        // for in 循环遍历  然后进行递归!
        for (let key in obj) {
            // 需要保证key 不是原型的属性
            if (obj.hasOwnProperty(key)) {
                result[key] = deepLoop(obj[key])
            }
        }
        return result
    }

注 : 自己学习整理,如果有不对的地方,还请多多指教,谢谢大家 ~!