首页 > 技术文章 > js垃圾回收机制与深拷贝和浅拷贝

15fj 2018-02-02 21:17 原文

垃圾收集

  • 作用:我们在学习闭包的时候,知道在IE里闭包容易引发内存泄漏。为什么会引发内存泄漏呢:
    因为IE9的javascript引擎使用的垃圾回收算法是引用计数法。对于循环引用的将导致垃圾回收无法回收“应该被回收”的内存。造成无意义的内存占用,也就是内存泄漏。
  • 内存泄漏
    指程序已动态分配的堆内存由于某种原因程序未释放或无法释放,造成造成内存的浪费,导致程序运行速度减慢甚至系统崩溃
  • 垃圾回收算法
    • 引用计数法:让所有的对象实现记录下有多少“程序”在引用自己。当程序执行完之后再将那些引用次数为零的将其清理
    • 标记清除法:分为两个阶段;标记阶段:将所有的活动对象做上标记,清除阶段:把没有标记的(非活动对象)销毁;可以解决循环引用的的问题

深拷贝与浅拷贝

  • 浅拷贝
    • 定义:JavaScript存储对象都是存地址的,所以浅拷贝会导致 obj1 和obj2指向同一块内存地址。改变了其中一方的内容,都是在原来的内存上做修改会导致拷贝对象和源对象都发生改变。
    • 举例:数组拷贝
        //浅拷贝,双向改变,指向同一片内存空间
        var arr1 = [1, 2, 3];
        var arr2 = arr1;
        arr1[0] = 'change';
        console.log('shallow copy: ' + arr1 + " );   //shallow copy: change,2,3
        console.log('shallow copy: ' + arr2 + " );   //shallow copy: change,2,3
    
    • 简单的引用复制
        function shallowClone(copyObj) {
        var obj = {};
        for ( var i in copyObj) {
          obj[i] = copyObj[i];
        }
        return obj;
      }
      var x = {
        a: 1,
        b: { f: { g: 1 } },
        c: [ 1, 2, 3 ]
      };
      var y = shallowClone(x);
      console.log(y.b.f === x.b.f);     // true
    
* ##### 深拷贝:
   * 是开辟一块新的内存地址,将原对象的各个属性逐个复制进去。对拷贝对象和源对象各自的操作互不影响。 
   * JSON对象是ES5中引入的新的类型(支持的浏览器为IE8+),JSON对象parse方法可以将JSON字符串反序列化成JS对象,stringify方法可以将JS对象序列化成JSON字符串,借助这两个方法,也可以实现对象的深拷贝。
   ```
       //例1
   var source = { name:"source", child:{ name:"child" } } 
   var target = JSON.parse(JSON.stringify(source));
   target.name = "target";  //改变target的name属性
   console.log(source.name); //source 
   console.log(target.name); //target
   target.child.name = "target child"; //改变target的child 
   console.log(source.child.name); //child 
   console.log(target.child.name); //target child
   //例2
   var source = { name:function(){console.log(1);}, child:{ name:"child" } } 
   var target = JSON.parse(JSON.stringify(source));
   console.log(target.name); //undefined
   //例3
   var source = { name:function(){console.log(1);}, child:new RegExp("e") }
   var target = JSON.parse(JSON.stringify(source));
   console.log(target.name); //undefined
   console.log(target.child); //Object {}
   ```

推荐阅读