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

2019-09-30  本文已影响0人  jadefan

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

堆(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),每次方法调用时都会在栈里储存一定信息(如参数、局部变量、返回值等等),这些信息再少也会占用一定空间,成千上万个此类空间累积起来,自然就超过线程的栈空间了。

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

上一篇下一篇

猜你喜欢

热点阅读