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

    正文概述 掘金(cn_gxf)   2021-03-12   557

    js中如何实现深浅拷贝? 项目开发中经常会遇到需要复制一个对象或者数组,但是却不能改变原始对象,所以就要用到拷贝,拷贝又分为深拷贝和浅拷贝

    浅拷贝

    自己创建一个新的对象,来接受你要重新复制或引用的对象值。如果对象属性是基本的数据类型,复制的就是基本类型的值给新对象;但如果属性是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存中的地址,肯定会影响到另一个对象。浅拷贝的方法有很多如Object.assign(),扩展运算符方式{...obj},数组 Array.from()等。就不一一列举了,手写一个浅拷贝

    思路

    • 对基础类型做一个最基本的拷贝;
    • 对引用类型开辟一个新的存储,并且拷贝一层对象属性;
        var Obj = { 
                func: function () { alert(1) },
                obj: {a:1,b:{c:2}},
                arr: [1,2,3],
                und: undefined, 
                reg: /123/,
                date: new Date(0), 
                NaN: NaN,
                infinity: Infinity,
                sym: Symbol(1)
          }
      const shallowClone = (target) => {
        if (typeof target === 'object' && target !== null) {
          const cloneTarget = Array.isArray(target) ? []: {};
          for (let prop in target) {
            if (target.hasOwnProperty(prop)) {
                cloneTarget[prop] = target[prop];
            }
          }
          return cloneTarget;
        } else {
          return target;
        }
      }
      shallowClone(Obj)
    

    结果如下

    js中如何实现深浅拷贝?

    深拷贝

    将一个对象从内存中完整地拷贝出来一份给目标对象,并从堆内存中开辟一个全新的空间存放新对象,且新对象的修改并不会改变原对象,二者实现真正的分离

    JSON.stringfy()是目前开发过程中最简单的深拷贝方法但是该方法拷贝也会存在一些问题,如下代码

        var Obj = { 
            func: function () { alert(1) },
            obj: {a:1},
            arr: [1,2,3],
            und: undefined, 
            reg: /123/,
            date: new Date(0), 
            NaN: NaN,
            infinity: Infinity,
            sym: Symbol(1)
      }
      Object.defineProperty(Obj,'innumerable',{ 
      enumerable:false,
      value:'innumerable'
      })
      JSON.parse(JSON.stringfy(Obj));
    

    结果如图所示 js中如何实现深浅拷贝? 注意

    • 拷贝的对象的值中如果有函数、undefined、symbol 这几种类型,经过 JSON.stringify 序列化之后的字符串中这个键值对会消失;
    • 无法拷贝对象的原型链、不可枚举的属性,以及对象的循环应用,即对象成环 (obj[key] = obj);
    • 拷贝 Date 引用类型会变成字符串;
    • 拷贝 RegExp 引用类型会变成空对象;
    • 对象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的结果会变成 null;

    该方法未拷贝对象所有属性,但是足以满足日常开发去需求

    递归版深拷贝

        //需要拷贝的对象
         var obj = {
          num: 0,
          str: '',
          boolean: true,
          unf: undefined,
          nul: null,
          obj: { name: '对象', id: 1, gender: 1  },
          arr: [0, 1, 2],
          func: function () { console.log('函数') },
          date: new Date(0),
          reg: new RegExp('/正则/ig'),
          [Symbol('1')]: 1,
        };
        Object.defineProperty(obj, 'innumerable', {
          enumerable: false, value: '不可枚举属性' }
        );
        obj = Object.create(obj, Object.getOwnPropertyDescriptors(obj))
        obj.loop = obj    // 设置loop成循环引用的属性
        //判断数据类型
        function ifType(val){
          let type  = typeof val;
          if (type !== "object") {
            return type;
          }
          return Object.prototype.toString.call(val).replace(/^\[object (\S+)\]$/, '$1');
        }
        //拷贝代码
        const deepClone = function (obj, hash = new WeakMap()) {
          if (ifType(obj) === 'Date') 
          return new Date(obj)       // 日期对象直接返回一个新的日期对象
          if (ifType(obj) === 'RegExp')
          return new RegExp(obj)     //正则对象直接返回一个新的正则对象
          //如果循环引用了就用 weakMap 来解决
          if (hash.has(obj)) return hash.get(obj)
          let allDesc = Object.getOwnPropertyDescriptors(obj)
          //遍历传入参数所有键的特性
          let copyObj = Object.create(Object.getPrototypeOf(obj), allDesc)
          //继承原型链
          hash.set(obj, copyObj)
          const isType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)
          for (let key of Reflect.ownKeys(obj)) { 
            copyObj[key] = (isType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]
          }
          return copyObj
        }
     //验证
    let copyObj = deepClone(obj)
    copyObj.arr.push(4)
    console.log('原始对象obj', obj)
    console.log('拷贝后的对象copyeObj', copyObj)
    

    除上以外,函数库lodash提供的_.cloneDeep方法也可以实现深拷贝


    起源地下载网 » js中如何实现深浅拷贝?

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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