js的深拷贝与浅拷贝的区别

一 堆(heap)和栈(stack)

栈(stack)会自动分配内存空间,会自动释放。堆(heap)动态分配的内存,大小不定也不会自动释放
堆(heap)和栈(stack)

栈(stack)会自动分配内存空间,会自动释放。堆(heap)动态分配的内存,大小不定也不会自动释放

二 说到深浅拷贝的时候就不得不说一下JS中的变量类型了:

基本类型: undefined、null、boolean、number、string, 按值存放在栈内存中的简单数据段, 可以直接访问.

引用类型: 存放在堆内存中的对象, 变量保存的是一个指向存放数据位置的指针. 访问引用类型(object, array)的值时, 首先从栈中获取到存放该数据位置的指针, 然后再从堆中取得数据.

浅拷贝: 浅拷贝是拷贝引用, 拷贝后的引用都是指向同一个存放数据位置的指针, 无论操作哪一个都是在操作指向在堆中的那一个数据, 所以双方都会有影响.
深拷贝: 在堆中重新分配内存, 将源对象的各个属性复制进去. 对拷贝对象和源对象各自操作互不影响.

三 深拷贝与浅拷贝的方法

  1. 浅拷贝的方法
    浅拷贝分两种情况, 拷贝源对象的引用和源对象拷贝实例, 但其属性拷贝引用.
**拷贝源的引用**
let obj1 = {name: 'jason'}
let obj2 = obj1
obj2.name = 'jack'
console.log(obj1)
// jack
**源对象拷贝实例, 其属性对象拷贝引用**
let obj1 = {
    a: 1,
    b: [1, 2, 3],
    c: {
        c1: 1
    }
};

let obj2 = Object.assign({}, obj1);
obj2.a = 2;
obj2.b[0] = 2;
obj2.c.c1 = 10
console.log(obj1);
/**
输出结果:
{
    a: 1, 
    b: [2, 2, 3],
    c: {
        c1: 10
    }
}
**/
          let obj = {
              name: 'jason',
              info: {
                  age: 16,
                  job: 'it'
              }
          }
          let obj2 = {...obj}
          obj2.name = 'jack ma'
          obj2.info.age = 19
          console.log(obj)
          输出结果:
          {
           info: {
                age: 19
				job: "it"
           },
			name: "jason"
          }

深拷贝

let obj1 = {
    a: 1,
    b: [‘hauwei’, ‘apple’, ‘mi’],
    c: {
        c1: 1
    }
};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj2.a = 2;
obj2.b[0] = 2;
obj2.c.c1 = 10
console.log(obj1);
/**
输出结果:
{
    a: 1, 
    b: [‘hauwei’, ‘apple’, ‘mi’],
    c: {
        c1: 1
    }
}

        function deepclone(source, target) {
            target = target || (Array.isArray(source) ? [] : {});
            for(let i in source) {
                if(typeof source[i] === 'object') {
                    target[i] = Array.isArray(source[i]) ? [] : {};
                    deepclone(source[i], target[i])
                } else {
                    target[i] = source[i]
                }
            };
            return target;
        }
**/
上一篇:记录一下动态代理


下一篇:关于String类型是否是引用类型