最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深浅拷贝

    正文概述 掘金(是J1AN_)   2020-12-23   419

    拷贝有个大前提,是针对对象的操作,当想复制一个对象的时候,才存在浅拷贝和深拷贝之分。浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用,如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。

    浅拷贝实现方式 (浅拷贝的意思就是只复制引用,而未复制真正的值)

            1.Object.assign() 拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。  可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

            2. ...展开运算符

    let obj1 = {name:"Kobe",address:{x:100,y:100}}
    let obj2 = {...obj1}
    obj1.address.x=200;
    obj1.name="wade";
    console.log(obj2)   //{name:"Kobe",address:{x:200,y:100}}
    // ... 实现的是对象第一层的深拷贝,后面的只是拷贝的引用值
    

            3. concat()  该方法可以连接两个或者更多的数组, 但是它不会修改已存在的数组,而是返回一个新数组

    let arr = [1,3,{
        username:"Kobe"
    }];
    let arr2 = arr.concat();
    arr2[2].username = 'wade';
    console.log(arr);
    // [1,3,{ username:"wade"};
    

          4. slice() 该方法不传值将会截取整个字段   slice只是对数组的第一层进行深拷贝

    let arr = [1,3,{
        username:'kobe'
    }];
    let arr2 = arr.slice();
    arr2[2].username = 'wade';
    console.log(arr) // [1,3,{username:'wade'}]
    

    数组有两个方法 concatslice 是可以实现对原数组的拷贝的,这两个方法都不会修改原数组,而是返回一个修改后的新数组。

    深拷贝实现方式(深拷贝就是对目标的完全拷贝,不像浅拷贝那样只是复制了一层引用,就连值也都复制了)

          1. JSON.parse(JSON.stringify()) 

    JSON.stringify 是将一个 JavaScript 值转成一个 JSON 字符串。

    JSON.parse 是将一个 JSON 字符串转成一个 JavaScript 值或对象。

    可以处理数组和对象的深拷贝,但是不能处理函数和正则,因为这两者基于这两个函数处理后得到的结果不再是正则/函数

     缺点: 

             1.会忽略undefined

             2.会忽略symbol

             3.不能序列化函数

             4.不能解决循环引用的对象

         2.如果所拷贝的对象含有内置对象,但是不包含函数,可以使用`messagechannel`,可以拷贝undefined和循环引用的对象

    function structuralClone(obj) {
            return new Promise(resolve => {
              const { port1, port2 } = new MessageChannel()
              port2.onmessage = ev => resolve(ev.data)
              port1.postMessage(obj)
            })
          }
          
          var obj = {
            a: 1,
            b: {
              c: 2
            }
          }
          
          obj.b.d = obj.b
          
          // 注意该方法是异步的
          // 可以处理 undefined 和循环引用对象
          const test = async () => {
            const clone = await structuralClone(obj)
            console.log(clone)
          }
          test()
    

         3.递归 (递归的思想就很简单了,就是对每一层的数据都实现一次 创建对象->对象赋值 的操作)

    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;
    }
    
    //演示
    const originObj = {  name:'axuebin',
      sayHello:function(){
        console.log('Hello World');
      }
    }
    console.log(originObj); // {name: "axuebin", sayHello: ƒ}
    const cloneObj = deepClone(originObj);
    console.log(cloneObj); // {name: "axuebin", sayHello: ƒ}
    

    总结: 

           1. 赋值运算符 = 实现的是浅拷贝,只拷贝对象的引用值;

           2. Javascript中数组和对象自带的拷贝方法都是"首层浅拷贝";

           3. JSON.stringify() 实现的是深拷贝,但是对目标对象有要求

           4. 若想真正意义上的深拷贝还是递归。


    起源地下载网 » 深浅拷贝

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元