javascript的一切實例都是對象,只是對象之間稍有不同,分爲原始類型和合成類型。原始類型對象指的是字符串(String)、數值(Number)、布爾值(Boolean),合成類型對象指的是數組(Array)、對象(Object)、函數(Function)。
既然對象分爲這兩類,他們之間的最大差別是複製克隆的差別。普通對象存儲的是對象的實際數據,而引用對象存儲的是對象的引用地址,而把對象的實際內容單獨存放,因爲引用對象通常比較龐大,這是數據開銷和內存開銷優化的手段。通常初學者很難理解這部分內容,就像對象的原型一樣,也是同一個概念。對象的原型也是引用對象,把原型的方法和屬性放在單獨內存當中,而對象的原型鏈則指向這個內存地址。儘管這部分內容比較拗口複雜,那其中的原理都是一致的,目的也一致。
1、原始類型對象的克隆
1.1、字符串的克隆
var x="1"; var y=x; y="2"; // "1" alert(x); // "2" alert(y);
1.2、數值的克隆
var x=1; var y=x; y=2; // 1 alert(x); // 2 alert(y);
1.3、布爾值的克隆
var x=true; var y=x; y=false; // true alert(x); // false alert(y);
2、合成類型對象的克隆
2.1、數組的克隆
如果採用普通克隆:
var x=[1,2]; var y=x; y.push(3); // 1,2,3 alert(x); // 1,2,3 alert(y);
由上可知,原始數組x,克隆數組y,修改了克隆數組y,但也同時修改了原始數組x,這就是引用對象的特點。那麼如何才能達到完整的數組克隆呢?
var x=[1,2]; var y=[]; var i=0; var j=x.length; for(;i<j;i++){ y[i]=x[i]; } y.push(3); // 1,2 alert(x); // 1,2,3 alert(y);
這樣,克隆數組y,原始數組x,兩個數組互補干擾,實現了完整的數組克隆。
2.2、對象的克隆
和數組的克隆同理,對象的完整克隆如下:
var x={1:2,3:4}; var y={}; var i; for(i in x){ y[i]=x[i]; } y[5]=6; // Object {1: 2, 3: 4} console.log(x); // Object {1: 2, 3: 4, 5: 6} console.log(y);
2.3、函數的克隆
var x=function(){alert(1);}; var y=x; y=function(){alert(2);}; // function(){alert(1);}; alert(x); // y=function(){alert(2);}; alert(y);
函數的克隆,使用“=”符號就可以了,並且在改變克隆後的對象,不會影響克隆之前的對象,因爲克隆之後的對象會單獨複製一次並存儲實際數據的,是真實的克隆。
3、完整的對象克隆
根據1和2,總結一下完整的對象克隆,包括克隆普通對象、引用對象。在寫這個方法之前,我們必須想到的是,克隆引用對象必須採用完整克隆(深度克隆),包括對象的值也是一個對象也要進行完整克隆(深度克隆)。
完整的對象克隆又稱爲深度對象克隆、對象的深度克隆、對象的深度複製等等。
- 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
- {
- //如果當前遍歷到的是一個obj的話, 創建一個obj對象, 遍歷當前obj的屬性
- o={};
- for(i in obj){
- //遍歷當前obj的屬性
- if(typeof(obj[i])=="object" && obj[i]!=null){
- o[i]=arguments.callee(obj[i]);
- }
- else{
- //遍歷到obj內的屬性, 直接使用"="進行賦值操作即可
- o[i]=obj[i];
- }
- }
- }
- return o;
- }