美文网首页
JS对象的引用与赋值

JS对象的引用与赋值

作者: 啊啊啊阿南 | 来源:发表于2018-01-18 11:36 被阅读0次

    javascript的一切实例都是对象,只是对象之间稍有不同,分为原始类型和合成类型。原始类型对象指的是字符串(String)、数值(Number)、布尔值(Boolean),合成类型对象指的是数组(Array)、对象(Object)、函数(Function)。

    既然对象分为这两类,他们之间的最大差别是复制克隆的差别。普通对象存储的是对象的实际数据,而引用对象存储的是对象的引用地址,而把对象的实际内容单独存放,因为引用对象通常比较庞大,这是数据开销和内存开销优化的手段。通常初学者很难理解这部分内容,就像对象的原型一样,也是同一个概念。对象的原型也是引用对象,把原型的方法和属性放在单独内存当中,而对象的原型链则指向这个内存地址。尽管这部分内容比较拗口复杂,那其中的原理都是一致的,目的也一致。

    引用

    var myArrayRef = new Array(0,1,2); //创建数组对象
    var mySeconArrayRef = myArrayRef; // 对象复制.
    myArrayRef[0] = 100; // 修改元素值
    alert(mySeconArrayRef[0]);
    
    /**
    *  javascript语言中创建的对象myArrayRef值中其时保存的是对象的引用(也就是一个地址). 
    *  也就是 我用 new Array生成的保存在内存中,而new Array把它所在的地方告诉了myArrayRef,
    *  myArrayRef又把这地址告诉了mySeconArrayRef 
    *  他们两个都指向的是new Array生成对象的地址而不是把对象保存在myArrayRef中,
    *  所以通过其中的一个去修改值时其时是修改他们同指象的那对象.
    */
    

    赋值

      var myVa = 'ABC'; //把ABC的值 赋予了myVa
      var myVb = myVa; // myVa 赋值给 myVb
      myVa = 'DEF'; //修改myVa
      console.log(myVa ); //ABC
    // 把值保存在了变量里, 而不是引用地址,所以他们两个是相对独立的整体.
    

    如果真要复制对象互不影响,则要通过转换赋值或者遍历key:value来复制你对象中的方法和属性

    jquery转换赋值

      var data = {a:1,b:2,c:3,d:[0,1,2,3]};
      var str = JSON.stringify(data);
      var data1 = $.parseJSON(str); //$为jQuery对象需要引入jQuery包
      data1["e"] = 4;
      data1["d"][0] = 11;
      console.log(data);
      console.log(data1);
    
    输出结果:
    {a: 1, b: 2, c: 3, d: [0,1,2,3]}
    {a: 1, b: 2, c: 3, d: [11,1,2,3], e: 4}
    
    相互没有影响
    

    浅拷贝

    我们需要封装一个函数,来对对象进行拷贝,通过for in 循环获取基本类型,赋值每一个基本类型,才能真正意义上的复制一个对象

      var obj = { a:10 };
      function copyObj(obj){
          var newobj = {};
          for ( var key in obj) {
              newobj[key ] = obj[key ];
          }
          return newobj;
      }
      var obj2 = copyObj(obj);
      obj2.a = 20;
      alert(obj.a); //10 
    

    深拷贝

    浅拷贝存在隐患,如果obj中,a的值不是10,而是一个对象,这样就会导致在for in中,将a这个对象的引用赋值为新对象,导致存在对象引用的问题

      var obj = {a:{b:10}};
      function copyObj(obj){
          var newobj = {};
          for ( var key in obj) {
              newobj[key ] = obj[key ];
          }
          return newobj;
      }
      var obj2 = copyObj(obj);
      obj2.a.b = 20;
      alert(obj.a.b); //20  
    

    因此,由于这个copy对象只是对第一层进行拷贝,无法拷贝深层的对象,这个copy为浅拷贝,对象的子对象也是引用,所以遍历赋值的时候要判断,子元素是否是对象,如果子元素是对象,则继续对子元素进行遍历赋值,我们需要通过递归,来拷贝深层的对象。

      var obj = {a:{b:10}};
      function deepCopyObj(obj){
          if(typeof obj != 'object'){
              return obj;
          }
          var newobj = {};
          for ( var attr in obj) {
              newobj[attr] = deepCopyObj(obj[attr]);
          }
          return newobj;
      }
      var obj2 = deepCopyObj(obj);
      obj2.a.b = 20;
      alert(obj.a.b); //10  
    

    对象引用做为函数参数传递

    对象引用做为函数参数传递时候,依然会相互影响,切记,如下示例:

    
      var data = {a:1,b:2,c:3,d:{q:4,w:5,e:6}};
      var data1 = data;
      function con(data2){
      data2["r"] = 5;
      console.log(JSON.stringify(data2));
      }
      con(data1);
      console.log(JSON.stringify(data));
    
    输出结果:
    
    {"a":1,"b":2,"c":3,"d":{"q":4,"w":5,"e":6},"r":5}
    {"a":1,"b":2,"c":3,"d":{"q":4,"w":5,"e":6},"r":5}
    

    对象引用赋值后,如果将对象置空,相互不受影响

      var arr = {"a":"1","b":"2"};
      var arr1 = arr;
      arr = {};
      arr["a"] = 2;
      console.log(arr1);
      console.log(arr);
    
    输出结果:{"a":"1","b":"2"},{"a":2}
    

    函数的克隆

    var x=function(){alert(1);};
    var y=x;
    y=function(){alert(2);};
    
    // function(){alert(1);};
    alert(x);
    
    // y=function(){alert(2);};
    alert(y);
    
    alert(x).png
    alert(y).png

    函数的克隆,使用“=”符号就可以了,并且在改变克隆后的对象,不会影响克隆之前的对象,因为克隆之后的对象会单独复制一次并存储实际数据的,是真实的克隆。

    完整的对象克隆

      function clone(obj) {
        var o,i,j,k;
        if(typeof(obj)!="object" || obj===null)return obj;
        if(obj instanceof(Array)) {
          o=[];
          i=0;
          j=obj.length;
          for(;i<j;i++)  {
            if(typeof(obj[i])=="object" && obj[i]!=null) {
              o[i]=arguments.callee(obj[i]);
            } else {
              o[i]=obj[i];
            }
          }
        }else {
          o={};
          for(i in obj){
            if(typeof(obj[i])=="object" && obj[i]!=null){
              o[i]=arguments.callee(obj[i]);
            }else{
              o[i]=obj[i];
            }
          }
        }
        return o;
      }
    

    相关文章

      网友评论

          本文标题:JS对象的引用与赋值

          本文链接:https://www.haomeiwen.com/subject/eswioxtx.html