zoukankan      html  css  js  c++  java
  • JS对象的深浅拷贝及其新增方法测试

      我们在了解数据类型的时候,都知道一般的字符,数值,undefined和布尔值等都为一般数据类型,它们在进行数据传输的时候,进行的是值传递,当我们修改新数据,是不影响老数据的。但是我们今天要讲的是数据类型中的一种复杂数据,它的代表就是对象。

    // 一般数据的值拷贝
      // 将a的值作为实参传入函数执行函数语句,虽然函数体内的参数发生了改变
      // 却不会影响原数据的值
      var  a = 10 ;
      function fn(a){
          a = 20;
          console.log(a);   //20
      }
      fn(a);
      console.log(a);    //10

      对象的传递是一种引用传递,当发生数据的拷贝时,对象传递的是内存地址的指向,将两个变量的指向拉到同一个地址上去了,这就会导致当我们对新拷贝数据进行修改的时候,老数据也会受到影响,值也会发生改变,但这种改变是一定的么?那也不一定,这就引入了我们今天要测试的内容:对象的深浅拷贝。

      首先我们先来测试一下浅拷贝,浅拷贝简单来说就是对象只拷贝了地址,不拷贝值,这种情况就会导致我们上面所说的情况,具体代码测试如下:

     1 // 对象的浅拷贝:
     2   //声明对象并赋值
     3   var obj = {
     4       name:"admin"
     5   }
     6   // 创建函数进行拷贝
     7   function fn(obj2){
     8   // 执行语句将obj2的name值改为root        
     9       obj2.name = "root"
    10   }
    11   //执行函数并将obj的值传参给函数
    12   fn(obj);
    13   // 打印返回obj,此时obj的值发生了改变
    14   console.log(obj);            //{name:"root"}

      另一种就是我们今天要着重要介绍的深拷贝,与浅拷贝恰恰相反,深拷贝是只拷贝原对象的值,不拷贝地址,而这种拷贝模式就会让我们在处理对象数据拷贝问题时,可以在拷贝数据的同时不影响老数据。一般实现的方法如下: 

    // 对象的深拷贝
      // 一般我们利用for in对对象实现遍历达到深拷贝的目的
      var obj = {
          name :"admin"
      }
      // 声明空对象
      var obj2 = {};
      // 遍历老对象,赋值给新对象
      for(var i in obj){
      // 这里的赋值仅为值的拷贝,并没有拷贝地址
          obj2[i]=obj[i];
      }
      // 改变新对象的值
      obj2.name = "root";
      // 返回结果并未对老对象的值产生影响
      console.log(obj);                //{name:"admin"}
      console.log(obj2);            //{name:"root"}

      通过上面的测试我们可以得出for in的遍历可以实现对对象的深拷贝,但是它就是完美无缺的么?答案肯定是否定的,下面看一种特殊的对象拷贝情景,来测试for in 拷贝的特点:

    // 特殊对象的拷贝,测试for in的深拷贝特点
      var obj = {
          name:{
              name:"admin"
          }
      }
      var obj2 = {};
      // 遍历老对象,赋值给新对象
      for(var i in obj){
          obj2[i] = obj[i]
      }
      // 测试第一层值是否被深拷贝  (结果是成立的)
      // obj2.name = "root";
      // console.log(obj);                //{name:name:"admin"}
      // console.log(obj2);            //{name:"root"}
      // 测试第二层值是否被深拷贝 (结果是否定的)
      obj2.name.name = "root";
      console.log(obj);                //{name:name: "root"}
      console.log(obj2);            //{name:name: "root"}
      // 继续测试如果对象有两层以上的值时,for in就实现不了对对象的深拷贝。
      // 例 :var obj = {
      //     name:{
      //         name:{
      //             name:"admin"
      //         }
      //     }
      // }
      // 感兴趣的朋友可以自行测试
      // 由此引出for in遍历只能实现一层深拷贝的特点

      for  in只能实现一层深拷贝,那有什么方法是可以实现对对象完全的深拷贝呢?答案当然也是肯定的,在ES5中我们将会了解到JSON.parse(str)和JSON.stringify(obj)两种实现json/对象的序列化和反序列化的方法,这里我简单介绍一下,JSON.parse(str)是用来将json字符转化成对象的方法,而JSON.stringify(obj)则是将对象转化为json字符串的方法。利用这两种方法我们来实现对象深拷贝的另一种方法:

    // 特殊对象的拷贝,测试JSON.parse(str)和JSON.stringify(obj)的深拷贝
      var obj = {
          name:{
              name:"admin"
          }
      }
     var obj2 = JSON.parse(JSON.stringify(obj));
     // 利用JSON.stringify(obj)将obj对象转化为json,再将json通过JSON.parse()重新转化为一个新的对象赋值给obj2;
      // 测试第一层值是否被深拷贝  (结果是成立的)
      // obj2.name = "root";
      // console.log(obj);                //{name:name:"admin"}
      // console.log(obj2);            //{name:"root"}
      // 测试第二层值是否被深拷贝 (结果是成立的)
      obj2.name.name = "root";
      console.log(obj);                //{name:name: "admin"}
      console.log(obj2);            //{name:name: "root"}
      // 即使是三层测试结果同样是成立的
    由此可得对象完全深拷贝新黑科技。
  • 相关阅读:
    linux 下查看文件修改时间
    ubuntu 把软件源修改为国内源和更新
    新概念 Lesson 10 Tired and thirsty What's the matter? Are you all right? That's all right!
    新概念 Lesson 9 How do you do? 你好! our,your,their复数形式的形容词性物主代词
    English trip EM4 LP1 A GETTing To Konw You Teacher:Olivia
    [转] CVE-2019-1367 脚本引擎内存损坏漏洞
    English trip EM3 LP 1B Have a good weekend Teacher:Ryan
    I4-6 Surprise Teacher:Lamb Talk about Holidays and Festives People do what
    English trip EM3 LP 4B Home Design Relationship Teacher:Ryan
    English trip EM3 LP4A ROOMS Teacher:Lamb
  • 原文地址:https://www.cnblogs.com/liguanlong/p/11431760.html
Copyright © 2011-2022 走看看