美文网首页
js中的堆、栈与深拷贝、浅拷贝

js中的堆、栈与深拷贝、浅拷贝

作者: jadefan | 来源:发表于2019-09-30 17:19 被阅读0次

    程序执行过程中的变量是需要保存起来供代码调用和计算的,这就用到了内存空间,分为堆和栈

    堆(heap)堆内存的简称,动态分配内存,内存大小不一,也不会自动释放。
    混沌无序,方便存储和开辟内存空间
    堆空间大,由用户控制释放。通过引用计数来控制生命期,回收器来释放最终的堆空间

    栈(stack)栈内存的简称,自动分配相对固定大小的内存空间,并由系统自动释放。
    线性结构,后进先出,便于管理

    堆栈与变量的存储关系

    5种基本类型:Undefined、Null、Boolean、Number和String

    基本类型都是直接按值存储在栈中的,每种类型的数据占用的内存空间的大小是确定的,并由系统自动分配和自动释放。这样带来的好处就是,内存可以及时得到回收,相对于堆来说,更加容易管理内存空间。

    引用类型 : 如对象(Object)、数组(Array)、函数(Function) …

    引用类型的数据存储于堆中,但是数据的地址指针是存储于栈中的,当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,在通过地址指针找到堆中的所需要的数据。

    深拷贝、浅拷贝

    基本类型拷贝的时候只是在内存中又开辟了新的空间,和原始变量相互独立,不存在深浅,因此深浅拷贝是相对于引用类型来说的

    浅拷贝 :引用类型在拷贝过程中,只是拷贝了存在栈内存中的指针,二者同时指向堆内存中相同数据
    深拷贝 :引用类型在拷贝过程中,需要将堆内存中的数据全部拷贝,分配新的存储空间和指针,以保证二者完全独立

    深拷贝的常用方法:

    最简单的通过JSON转换,适用于没有函数的对象

        function deepCopy(obj) {
            return JSON.parse(JSON.stringify(obj));
        }
    

    或者遍历对象中的所有属性和方法,一直找到最下层的基本类型为止,全部拷贝
    借用大佬的代码

      //这里为了阅读方便,只深拷贝对象,关于数组的判断参照上面的例子
       function deepClone(data){
           var obj = {};
           var originQueue = [data];
           var copyQueue = [obj];
           //以下两个队列用来保存复制过程中访问过的对象,以此来避免对象环的问题(对象的某个属性值是对象本身)
           var visitQueue = [];
           var copyVisitQueue = [];
           while(originQueue.length > 0){
               var _data = originQueue.shift();
               var _obj = copyQueue.shift();
               visitQueue.push(_data);
               copyVisitQueue.push(_obj);
               for(var key in _data){
                   var _value = _data[key]
                   if(typeof _value !== 'object'){
                       _obj[key] = _value;
                   } else {
                       //使用indexOf可以发现数组中是否存在相同的对象(实现indexOf的难点就在于对象比较)
                       var index = visitQueue.indexOf(_value);
                       if(index >= 0){
                           // 出现环的情况不需要再取出遍历
                           _obj[key] = copyVisitQueue[index];
                       } else {
                           originQueue.push(_value);
                           _obj[key] = {};
                           copyQueue.push(_obj[key]);
                       }
                   }
               }
           }
           return obj;
       }
    
    堆栈的大小问题

    堆栈是在内存中的空间,大小就会有显示限制,浏览器会有自动垃圾回收机制,但代码的优化也很重要

    每次执行代码时,都会分配一定尺寸的栈空间(Windows系统中为1M),每次方法调用时都会在栈里储存一定信息(如参数、局部变量、返回值等等),这些信息再少也会占用一定空间,成千上万个此类空间累积起来,自然就超过线程的栈空间了。

    尤其发生在大数据量的递归处理时,后续介绍处理办法。

    相关文章

      网友评论

          本文标题:js中的堆、栈与深拷贝、浅拷贝

          本文链接:https://www.haomeiwen.com/subject/hplhpctx.html