zoukankan      html  css  js  c++  java
  • 深拷贝、浅拷贝的实现

    深拷贝、浅拷贝实现

    JavaScript的数据类型分为基本数据类型和引用数据类型。

    5种基本数据类型Undefined、Null、Boolean、Number 和 String,变量是直接按值存放的,存放在栈内存中的简单数据段,可以直接访问。

    检测对象的判断

    function isObject(obj) {
        return Object.prototype.toString.call(obj) === '[object Object]';
    }

    不太适合本文,本文包括数组

    []和{} ,null的都是object

    可以用

    function isObject(obj) {
        return typeof obj === 'object' && obj != null;
    }

    也可以用如果值是对象用下面

    source[keys] && typeof source[keys] === 'object'

    对于基本数据类型的拷贝,并没有深浅拷贝的区别,我们所说的深浅拷贝都是对于引用数据类型而言的。

    浅拷贝的意思就是只复制引用,而未复制真正的值。

    const originArray = ['火影忍着','海贼王','名侦探柯南'];
    const originObj = {
      name: 'sophia',
      age: 18,
      hobby: ['swimming', 'shopping', [1, 2, [ 'a', 'b']]],
      book: {
          title: "Node.js实战",
          price: "69",
          content: ['1章', '2章']
      },
      print: function(){
          console.log('--print-->', this.name)
      },
      t1: undefined,
      t2: null,
      t3: 123
    };

    一、浅拷贝的实现方式

    1、模拟一个浅拷贝函数

    遍历对象,然后把属性和属性值都放在一个新的对象

    var shallowCopy = function(obj) {
        // 只拷贝对象
        if (typeof obj !== 'object') return;
        // 根据obj的类型判断是新建一个数组还是对象
        var newObj = obj instanceof Array ? [] : {};
        // 遍历obj,并且判断是obj的属性才拷贝
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = obj[key];
            }
        }
        return newObj;
    }

    二、深拷贝实现

    目前实现深拷贝的方法不多,主要是两种:

    1、利用 JSON 对象中的 parse 和 stringify

    利用递归来实现每一层都重新创建对象并赋值

    const originArray = [1,2,3,4,5];
    const cloneArray = JSON.parse(JSON.stringify(originArray));
    console.log(cloneArray === originArray); // false
    
    const originObj = {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};
    const cloneObj = JSON.parse(JSON.stringify(originObj));
    console.log(cloneObj === originObj); // false
    
    cloneObj.a = 'aa';
    cloneObj.c = [1,1,1];
    cloneObj.d.dd = 'doubled';
    
    console.log(cloneObj); // {a:'aa',b:'b',c:[1,1,1],d:{dd:'doubled'}};
    console.log(originObj); // {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};

    但是有缺陷

    undefined、function、symbol 会在转换过程中被忽略,就是说如果对象中含有一个函数时(很常见),就不能用这个方法进行深拷贝

    const originObj = {
      name:'axuebin',
      sayHello:function(){
        console.log('Hello World');
      }
    }
    console.log(originObj); // {name: "axuebin", sayHello: ƒ}
    const cloneObj = JSON.parse(JSON.stringify(originObj));
    console.log(cloneObj); // {name: "axuebin"}

    另外数组有两个方法 concat 和 slice 是可以实现对原数组的拷贝的,这两个方法都不会修改原数组,而是返回一个修改后的新数组,同时,ES6 中 引入了 Object.assgn 方法和 ... 展开运算符也能实现对对象的拷贝。但他们对于多层数组不适用,只拷贝第一层数组

    2、递归的方法

    递归的思想就很简单了,就是对每一层的数据都实现一次 创建对象->对象赋值 的操作,简单粗暴上代码



    function deepClone(source){
      const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
      for(let keys in source){ // 遍历目标
        if(source.hasOwnProperty(keys)){
          if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
            targetObj[keys] = source[keys].constructor === Array ? [] : {};
            targetObj[keys] = deepClone(source[keys]);
          }else{ // 如果不是,就直接赋值
            targetObj[keys] = source[keys];
          }
        } 
      }
      return targetObj;
    }

     

  • 相关阅读:
    强化学习 | D3QN原理及代码实现
    Airtest入门及多设备管理总结
    JS图片base64压缩
    ABP框架
    .net gof23种设计模式
    VS2013添加Socket
    VS2013用InstallShield打包winfrom项目
    .net core3.1 log4net无法写日志
    git commit 修改提交说明信息
    screen 使用总结
  • 原文地址:https://www.cnblogs.com/pikachuworld/p/12806268.html
Copyright © 2011-2022 走看看