用淺/深拷貝、和HTML5方法解決js對象的引用的問題


先來看一個例子

例一:

var a=[1,2,3];
var b=a;
b.push(4);
alert(b);//1,2,3,4
alert(a);//1,2,3,4
var a=[1,2,3];
var b=a;
b=[1,2,3,4]
alert(b);//1,2,3,4
alert(a);//1,2,3

這兩種方法得出的結果是不一樣的。

第一個程序,是對象的引用, 把a的值附給b,a與b之間是引用的關系,當兩者之間是引用的關系時,改變任一變量,都會影響另一個變量。

第二個程序,只是對b的值改變,雖然b=a ,但是當改變b的值時,又重新建立了一個地址,這個地址與a無關,所以在改變b值時,與a無關,這有點類似於C中的指針

再來看一個例子

例二:

var a={
     name:'hello'          
};
var b=a;
b.name='hi';
alert(a.name);//當然了,這個結果肯定是hi

如何解決上面的問題呢?

var a={
     name:'hello'          
};
function copy(a){
    var b={};
    for(var attr in a){
        b[attr]=a[attr]
    }    
   return b  
}
copy(a).name='hi';
alert(a.name); //這時的結果就是hello了
        

上面的方法叫淺拷貝,利用for in 把a中屬性拷貝給b,但是只是拷貝了一個副本,實際上當修改b的值是不會改變a的值的。當然有淺拷貝就有深拷貝。

var a={
     name:{value:'world'}          
}
function copy(a){
    var b={};
    for(var attr in a){
        b[attr]=a[attr];
    }    
   return b  
}
copy(a).name.value='space';
alert(a.name.value); //這時的結果是space

這時候大家或許或納悶,用了拷貝了怎么結果還是space呢!因為JSON里面又有一個 value:'world' 這個類型是一個對象,你拷貝過來還是對象,還是對象的引用,所以結果就是space,當然了,或許有會說那就再用一次copy就行。由結果再調用一次copy,對了,就是遞歸的含義,在函數內部調用函數本身。稍微修改一下程序即可

var a={
     name:{value:'world'}          
}
function deepCopy(a){
     if(typeof a!='object'){
        return a
    }   
    var b={};
    for(var attr in a){
        b[attr]=deepCopy(a[attr]);
    }    
   return b  
}
deepCopy(a).name.value='space';
alert(a.name.value); //這時的結果就是world

改的地方有兩處,1、執行函數內部調用函數本身   b[attr]=deepCopy(a[attr])   2、終止條件typeof a!='object'  就像上面說的,你用淺拷貝拷的是對象,終止條件就是檢測類型不是對象的時候,返回a的值。這樣就解決了問題。 上面的方法就是深拷貝

例三:

現在了解了淺/深拷貝,想用HTML5方法去解決。在解決之前,我們很有必要去了解HTML5之前如何將字符串轉換成js語句,如下:

var str='function task(){alert('hello')}'
var fn=eval(str);
task(); //hello

HTML5如何把JSON格式的字符串轉成JSON對象,用JSON.parse() 如下:

var a='{
  'name':'hello';  
};'
var json=JSON.parse(a);
alert(json.name); //hello

這個name上加了 ' '  不加' ' 是不嚴格的JSON,JSON.parse 方法要求必須是嚴格的JSON

如何將JSON對象轉成JSON格式的字符串呢,用JSON.stringify()  如下:

var a={
   name:'hello'  
};
var json=JSON.stingify(a);
alert(json); // '{'name':'hello'}'
這時的結果就是 '{'name':'hello'}',這時候就明白了為什么要用嚴格的JSON格式了

那么用HTML5怎么解決問題呢,那就先把JSON轉成字符串,再把JSON格式的字符換轉成對象,實際上引用的還是a的副本,並沒有真正引用a。這就和拷貝中的
副本原理是一樣的。如下:
var a={
    name:'hello'  
};
var str=JSON.stringify(a);
var obj=JSON.parse(str);
var b=obj;
b.name='hi';
alert(a.name);//hello
拓展:

   這種方法實際上在8以下是不兼容的,如何兼容呢,就是引用一個json文件:json2.js,如下

<script type='text/javascript' src='json2.js'></script>

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM