遞歸實現(xiàn)深度克隆(內(nèi)含JS數(shù)據(jù)類型判斷残吩,對象遍歷)

轉(zhuǎn)自:http://blog.csdn.net/qq_27090183/article/details/50823429


使用遞歸來實現(xiàn)一個深度克隆财忽,可以復制一個目標對象,返回一個完整拷貝
被復制的對象類型會被限制為數(shù)字泣侮、字符串即彪、布爾、日期、數(shù)組隶校、Object對象漏益。不會包含函數(shù)、正則對象等

首先要去判斷要克隆的對象的值類型或者引用類型深胳。判斷方法有很多種绰疤!

對于值類型或者引用有4種方法判斷:

1.typeof

但是!js的數(shù)值有兩種構(gòu)造方法:直接賦值法和通過值函數(shù)構(gòu)造器構(gòu)造
例如:

var test1 = "string"; 
var test2 = new String("string2"); 
console.log(typeof test1);//輸出string
console.log(typeof test2);//輸出object

對于typeof來說舞终;所有通過構(gòu)造器constructor產(chǎn)生的變量都是object.那么我們怎么去判斷用constructor產(chǎn)生的變量轻庆?

2.instanceof

instanceof 函數(shù)可以判斷左邊參數(shù)是否是右邊參數(shù)的一個實例!
例如:

console.log(test2 instanceof String);//輸出true
console.log(test1 instanceof String);//輸出false

這就很不和諧了敛劝!有沒有兩種都能判斷的方法呢余爆?

3.Object.prototype.toString.call()

當然有!MDN在官方教程上就介紹了一種可以判斷所有類型的方法夸盟!
使用toString()方法來檢測對象類型

console.log(Object.prototype.toString.call(test1))//輸出[object String] 
console.log(Object.prototype.toString.call(test1))//輸出[object String]

頓時覺得人生豁然開朗了起來蛾方!啊~五環(huán)!你比四環(huán)多一環(huán)满俗!

4.Object.constructor

在研究MDN 的api文檔的時候转捕,發(fā)現(xiàn)了constructor方法!
無論怎么樣唆垃,這個方法都返回一個指向創(chuàng)建了該對象原型的函數(shù)引用。

需要注意的是痘儡,該屬性的值是那個函數(shù)本身辕万, 而不是一個包含函數(shù)名稱的字符串!
對于原始值(如1沉删,true 或 “test”)渐尿,該屬性為只讀。 所有對象都會從它的原型上繼承一個constructor屬性. 所以矾瑰,雖然可以實現(xiàn)判斷砖茸,但是還是不用為好!

console.log(test1.constructor.toString()=="function String() { [native code] }")//true; 
console.log(test2.constructor.toString()=="function String() { [native code] }")//true;

總結(jié):方法3殴穴、4對于所有值類型和引用類型適用(推薦第三種方法凉夯,畢竟官方),第12種方法看情況使用采幌!

然后來到遍歷問題了劲够!
1.字符串的遍歷

 var temp = src.split(""); 
var cloneString=""; 
for(var i=0;i<temp.length;i++) 
{ 
    cloneString+=temp[i]; 
}

原理就是利用split()方法將字符串里一個個字母分開(注意里面的參數(shù)為空 "",為其他就會以這個參數(shù)為標準分離字符串)

2.數(shù)組的遍歷
使用的是傳統(tǒng)的數(shù)組遍歷

var temp = new Array(); 
for(var i=0,a;a = array[i];i++) 
{ 
    temp[i] = cloneObject(a); 
}

這里遇到了幾個坑,先說一下: 當使用

for(var a in array)
{
    console.log(a+typeof a)
}

得到的值是 0 string 1 string 2 string 這種方法并不行 還有一個坑就是當使用
for(var i=0,a;a = array[i++];)時 i會在a被賦值后就自動增加而不是等到一個循環(huán)完成再增加 休傍;也就是遍歷結(jié)果是對的征绎,但是i的數(shù)值變化是從1開始而不是從0開始的!
在賦值的過程中磨取,我首先使用的是temp.push()方法人柿!但是柴墩!push方法會讓temp數(shù)組新增加的元素的類型為undefined!這不是我想要的結(jié)果凫岖!我要的是完美克隆江咳,即數(shù)組里面對象類型也要和原來的一致。

看了MDN的api接口發(fā)現(xiàn)解決方法如下:
Array.prototype.push.apply(temp,array);

3.對象的遍歷
var temp = {}; var keys = Object.keys(src); // keys 為對象src的鍵名字數(shù)組
// 它是數(shù)組0亍T住!

for(var i=0,a;a=keys[i];i++) 
{
    temp[a] = cloneObject(src[a]); 
}

對象的遍歷婶芭,首先獲得它的鍵數(shù)組(對象自帶的keys()方法)东臀,然后再通過鍵遍歷一次值就行了,很簡單犀农。

多看MDN總會有收獲惰赋!下面附上我的代碼!

var cloneObject = function(src){
    var Result;
    switch(Object.prototype.toString.call(src)){
        case "[object Number]": 
            Result = (typeof src === "object"?new Number(src):parseInt(src.toString()));
            break;
        case "[object String]":
            // 遍歷字符串 =.= 好像沒啥意義
            // {
            //  var temp = src.split("");
            //  var cloneString="";
            //  for(var i=0;i<temp.length;i++)
            //  {
            //      cloneString+=temp[i];
            //  }
            // }
            Result = (typeof src === "object"?new String(src):src.toString());
            break;
        case "[object Boolean]":
            Result = (typeof src === "Boolean"?new Boolean(src):src);
            break;
        case "[object Date]":
            Result = new Date(src);
            break;
        case "[object Array]":
            var temp = new Array();
              // Array.prototype.push.apply(temp,src);
             // 當使用for(var i=0,a;a = src[i++];) i會在a被賦值后就自動增加而不是
             // 等到一個循環(huán)完成再增加
            for(var i=0,a;a = src[i];i++)
            {
                  // temp.push(cloneObject(a));
                  // 使用push方法會讓數(shù)組所有元素的類型變成undfined
                 temp[i] = cloneObject(a);
            }
            Result = temp;
            delete temp;
            break;
        case "[object Object]":
            var temp = {}; 
            var keys = Object.keys(src);
            // keys 為對象src的鍵名字數(shù)組
            // 它是數(shù)組:巧凇A薇簟!
            for(var i=0,a;a=keys[i];i++)
            {
                temp[a] = cloneObject(src[a]);
            }
            Result = temp;
            delete temp;
            delete keys;
            break;
        default:
            break;
    }
    return Result;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末孟害,一起剝皮案震驚了整個濱河市拒炎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挨务,老刑警劉巖击你,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異谎柄,居然都是意外死亡丁侄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門朝巫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸿摇,“玉大人,你說我怎么就攤上這事劈猿∽炯” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵糙臼,是天一觀的道長庐镐。 經(jīng)常有香客問我,道長变逃,這世上最難降的妖魔是什么必逆? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上名眉,老公的妹妹穿的比我還像新娘粟矿。我一直安慰自己,他們只是感情好损拢,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布陌粹。 她就那樣靜靜地躺著,像睡著了一般福压。 火紅的嫁衣襯著肌膚如雪掏秩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天荆姆,我揣著相機與錄音蒙幻,去河邊找鬼。 笑死胆筒,一個胖子當著我的面吹牛邮破,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仆救,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼抒和,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了彤蔽?” 一聲冷哼從身側(cè)響起摧莽,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎顿痪,沒想到半個月后范嘱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡员魏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了叠聋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撕阎。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碌补,靈堂內(nèi)的尸體忽然破棺而出虏束,到底是詐尸還是另有隱情,我是刑警寧澤厦章,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布镇匀,位于F島的核電站,受9級特大地震影響袜啃,放射性物質(zhì)發(fā)生泄漏汗侵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晰韵。 院中可真熱鬧发乔,春花似錦、人聲如沸雪猪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽只恨。三九已至译仗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間官觅,已是汗流浹背纵菌。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缰猴,地道東北人产艾。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像滑绒,于是被迫代替她去往敵國和親闷堡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,934評論 6 13
  • 1.通過typeof可以判斷處幾種基本數(shù)據(jù)類型Boolean,number,string,null,undefin...
    舟漁行舟閱讀 634評論 0 1
  • 中山路步行街逛吃逛吃 【1.蓮歡海蠣煎】放棄了唾手可得的“黃則和”疑故、“撈海塢”杠览、“黃榕樹下”……堅持尋到這家...
    i小森閱讀 828評論 3 9
  • 太陽剛剛升到頭頂?shù)拇笾形纾粋€人坐在空曠的自習室里纵势,捧著書咬著筆看著黑板默默發(fā)呆踱阿。這樣一個懶散的生活狀態(tài)...
    工科小蝦閱讀 325評論 25 2
  • 李白的劍 他是我最好的朋友。身高175钦铁,不胖不瘦软舌。卷卷的頭發(fā),深凹的眼眶牛曹,挺翹的鼻梁佛点,薄薄的嘴唇。 ...
    八咫閱讀 228評論 1 0