JavaScript:深拷贝和浅拷贝时,栈(stack)和堆(heap)这俩货扮演什么角色?

栈(stack)&&堆(heap):

栈(stack)内存:操作系统分配的固定空间,程序运行结束后自动释放,储存基本变量,以及一些对象的引用变量;JavaScript中的基本数据类型(String,Boolean,Number,Undefined,Null);

堆(heap)内存:操作系统动态分配空间,空间大小不定,不能自动释放(可通过人为操作或者垃圾回收机制释放);在堆中的变量可能在多个地方引用达到代码重复使用的目的;JavaScript的引用数据类型(Array,Function,Object);

注释:才疏学浅,多方借鉴,方能一吐笔墨,接下来有请灵魂画手---当代非著名画家闪亮登场!

传值&&传址:

先扫一眼这几行代码  0_0

        testArray(){
            let a = [1,2,3,4,5];
            let b = a;
            b[0] = 7
            let c= 0;

            console.log(`a-->`,a); // a--> (5) [7, 2, 3, 4, 5]
            console.log(`b-->`,b); // b--> (5) [7, 2, 3, 4, 5]
            console.log(`c-->`,c); // c--> 0
        }

惊奇的发现:

  1. [1,2,3,4,5]赋值给a,a赋值给b,输出a,b惊人的一致;
  2. 修改b[0]值,结果数组a也发生了一内内变化;
  3. 修改c,a和b并没发生改变(大哥,先把刀收起来,自己人),其实我是把b[0]赋值给c,输出一下,然后把0又赋值给c的,代码上没写b[0]赋值给c的!
  4. 这时我想stack和heap这俩货在做什么见不得人的操作,这时我突然想起来鲁迅,对,就是那个学生时代我最恨得人,课文不是要背诵就是谈理解T_T;

鲁迅说:你们抓周树人和我鲁迅有啥关系!就好像说你操作b,跟我a有啥联系一样,别说,还真有关系;

我去找找砸门的灵魂画手 ^_^

我简单画了一下,数组a,是引用数据类型在堆(heap)里面;也就是说当a赋值给b的时候,是把heap里的地址赋值给了b,自然操作b时会联动a也发生里改变;而c是仅仅从a获取里一个数值,这个数值是Number,存放在stack里面,修改c是在stack里面修改;

浅拷贝&&深拷贝:

我们知道基本数据类型和引用数据类型分别在stack和heap里面,理解浅拷贝和深拷贝就容易了!(我是这样认为的)

浅拷贝:

        copy(){
            let a = {
                A : "A"
            };
            a.AA = ["A","AA"];
            let b = shallowCopy(a);
            console.log(`a-->`,a); // a--> {A: "A", AA: ["A","AA"]}
            console.log(`b-->`,b); // b--> {A: "A", AA: ["A","AA"]}
            function shallowCopy(o) {
                let c = {};
                for(let i in o){
                    c[i] = o[i];
                }
                 return c;
            };
        }

对b进行b.AA.push("AAA")操作之后:

        copy(){
            let a = {
                A : "A"
            };
            a.AA = ["A","AA"];
            let b = shallowCopy(a);
            b.AA.push("AAA")
            console.log(`a-->`,a); // a--> {A: "A", AA: ["A","AA","AAA"]}
            console.log(`b-->`,b); // b--> {A: "A", AA: ["A","AA","AAA"]}
            function shallowCopy(o) {
                let c = {};
                for(let i in o){
                    c[i] = o[i];
                }
                 return c;
            };
        }

惊奇发现:操作b时,联动a也发生一内内变化;明显我们操作得是变量b里面的数组!

接下来再操作b,给b里面添加一个{B:"B"} 代码:

        copy(){
            let a = {
                A : "A"
            };
            a.AA = ["A","AA"];
            let b = shallowCopy(a);
            b.AA.push("AAA")
            b.B = "B";

            console.log(`a-->`,a); // a--> {A: "A", AA: ["A","AA","AAA"]}
            console.log(`b-->`,b); // b--> {A: "A", AA: ["A","AA","AAA"],B: "B"}

            function shallowCopy(o) {
                let c = {};
                for(let i in o){
                    c[i] = o[i];
                }
                 return c;
            };
        }

惊奇发现:操作b里面的数组会联动到变量a,那为什么操作b,不操作b里面对象A和数组AA时,也不见变量a里面添加B:"B",为什么啊!

请非著名画家---->

呸....画的真丑!

简单理解就是:当对变量a进行拷贝时,a变量中遇到基本数据类型直接以等号复制,如果在a变量中有引用数据类型比如上图中的AA是一个数组,Array是引用数据类型,在堆中且有地址,所以b拷贝过去的其实是AA在堆里面的地址,这也就是说,为什么对b里面的数组进行操作会联动到a里面的数组了!

深拷贝:

理解浅拷贝,那根据浅拷贝的提示,直接对拷贝对象中引用数据类型进行递归层层赋值就行了;

    copy() {
      let a = {
        A: "A",
      };
      function deepCopy(o, c) {
        var c = c || {} || [];
        for (let i in o) {
          if (typeof o[i] === "object") {
            c[i] = o[i].constructor === Array ? [] : {};
            deepCopy(o[i], c[i]);
          } else {
            c[i] = o[i];
          }
        }
        return c;
      }
      a.AA = ["A", "AA"];
      let b = {};
      b = deepCopy(a, b);
      b.AA.push("AAA");
      b.B = "B";
      console.log(`a-->`, a); // a--> {A: "A", AA: ["A","AA"]}
      console.log(`b-->`, b); // b--> {A: "A", AA: ["A","AA","AAA"],B: "B"}
    }

如上所见,对b进行push()操作还是添加B都没有联动到a,a真特么稳如老狗!

图我就不画了,递归层层赋值copy,a里面的AA和b里面的AA已经不是一个堆地址!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值