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

    正文概述 掘金(bysun)   2021-06-15   575

    1.前言

    深拷贝和浅拷贝是经常在面试中会出现的,主要考察你对基本类型和引用类型的理解深度。

    说到深浅拷贝,那在这就不得不提一下内存和数据类型了。

    在JS当中,数据类型分为基本数据类型和引用类型,其中基本数据类型(string,number,boolean,undefined,null,symnol......),引用类型为Object(Array、Object、Function......)。内存分为栈内存和堆内存,其中栈内存用来存储基本数据类型(存取速度快,存放量小)和引用类型的地址(存取速度慢,存放量大,其引用指针存于栈区,并指向引用本身),而堆内存则存储引用数据类型。

    2.赋值

    赋值是将某一数值或对象赋给某个变量的过程

    2.1 基本数据类型:赋值,赋值之后两个变量互不影响
    2.2 引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象,相互之间有影响
    <script>
        // 基本类型
        var a = 100;
        var b = a;
        a = 200;
        console.log(a, b); // 200, 100 ,a b指向不同的数据
    
        // 引用类型指向同一份数据
        var a = { c: 1000 };
        var b = a;
        a.c = 2000;
        console.log(a.c, b.c); // 2000, 2000 全是2000,a b指向同一份数据
    </script>
    

    通常在开发中并不希望改变变量 a 之后会影响到变量 b,这时就需要用到浅拷贝和深拷贝。

    3.浅拷贝

    3.1 创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

     <script>
      function cloneShallow(source) {
        var target = {};
        for (var key in source) {
          if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key];
          }
        }
        return target;
      }
      var a1 = { b: { c: {} } };
      var a2 = cloneShallow(a1); // 浅拷贝
      a2.b.c = { d: "1" };
      console.log("a1---", a1);
      console.log("a2---", a2);
    
      var a5 = { b: { d: [1,2] } };
      var a6 = cloneShallow(a5); // 浅拷贝
      a6.b.d = [3,4];
      console.log("a5---", a5);
      console.log("a6---", a6);
    
      // 注意:当object只有一层的时候,是深拷贝,例如如下:
      var a3 = { b:'9'};
      var a4 = cloneShallow(a3);
      a4.b = '10';
      console.log("a3---", a3);
      console.log("a4---", a4);
    </script>
    

    理解js中的深拷贝和浅拷贝

    3.2 Object.assign()

    Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。注意,Object.assgin() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

    Object.assign(target, ...sources)

    理解js中的深拷贝和浅拷贝

    3.3 Array.prototype.concat()

    理解js中的深拷贝和浅拷贝

    3.4 Array.prototype.slice()

    理解js中的深拷贝和浅拷贝

    3.5 ...obj 展开运算符

    展开运算符是 ES6 中新提出来的一种运算符。

    理解js中的深拷贝和浅拷贝

    4.深拷贝

    4.1 深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响

    <script>
      function isObject(obj) {
        return typeof obj === "object" && obj != null;
      }
      function cloneDeep(source) {
        if (!isObject(source)) return source; // 非对象返回自身
    
        var target = Array.isArray(source) ? [] : {};
        for (var key in source) {
          if (Object.prototype.hasOwnProperty.call(source, key)) {
            if (isObject(source[key])) {
              target[key] = cloneDeep(source[key]); // 注意这里
            } else {
              target[key] = source[key];
            }
          }
        }
        return target;
      }
      var obj = {
        title: "study",
        list: ["1", "2", "3"],
      };
      var obj2 = cloneDeep(obj);
      obj2.title = "play";
      obj2.list = ["3", "4"];
      console.log("obj", obj);
      console.log("obj2", obj2);
    </script>
    

    理解js中的深拷贝和浅拷贝

    4.2 JSON.parse(JSON.stringify(object))

    JSON.stringify():将对象转成 JSON 字符串。
    JSON.parse():将字符串解析成对象。
    通过 JSON.parse(JSON.stringify()) 将 JavaScript 对象转序列化(转换成 JSON 字符串),再将其还原成 JavaScript 对象,一去一来我们就产生了一个新的对象,而且对象会开辟新的栈,从而实现深拷贝。
    注意
    注意,该方法的局限性:
    1、不能存放函数或者 Undefined,否则会丢失函数或者 Undefined;
    2、不要存放时间对象,否则会变成字符串形式;
    3、不能存放 RegExp、Error 对象,否则会变成空对象;
    4、不能存放 NaN、Infinity、-Infinity,否则会变成 null;
    5、……更多请自行填坑,具体来说就是 JavaScript 和 JSON 存在差异,两者不兼容的就会出问题。

    理解js中的深拷贝和浅拷贝

    4.3 函数库 Lodash

     cloneDeep() 方法
    
    npm i --save lodash
    var _ = require('lodash');
    
    var objects = [{ 'a': 1 }, { 'b': 2 }];
    var deep = _.cloneDeep(objects);
    console.log(deep[0] === objects[0]);
    // => false
    
    

    5.总结

    通过学习整理了解到了深拷贝和浅拷贝的差异,在写业务代码的时候根据场景更好的拷贝数据,当然,文章也存在部分逻辑的不完整性,欢迎大家指正。

    6 参考

    木易杨前端进阶


    起源地下载网 » 理解js中的深拷贝和浅拷贝

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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