精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

低門檻徹底理解JavaScript中的深拷貝和淺拷貝

開發 前端
Javascript深拷貝和淺拷貝是初學者甚至有經驗的開發者,都會經常遇到問題,本文作者帶你低門檻徹底理解JavaScript中的深拷貝和淺拷貝。

[[228890]]

在說深拷貝與淺拷貝前,我們先看兩個簡單的案例:

 

  1. //案例1  
  2. var num1 = 1, num2 = num1;  
  3. console.log(num1) //1  
  4. console.log(num2) //1  
  5. num2 = 2; //修改num2  
  6. console.log(num1) //1  
  7. console.log(num2) //2  
  8. //案例2  
  9. var obj1 = {x: 1, y: 2}, obj2 = obj1;  
  10. console.log(obj1) //{x: 1, y: 2}  
  11. console.log(obj2) //{x: 1, y: 2}  
  12. obj2.x = 2; //修改obj2.x  
  13. console.log(obj1) //{x: 2, y: 2}  
  14. console.log(obj2) //{x: 2, y: 2} 

按照常規思維,obj1應該和num1一樣,不會因為另外一個值的改變而改變,而這里的obj1 卻隨著obj2的改變而改變了。同樣是變量,為什么表現不一樣呢?這就要引入JS中基本類型和引用類型的概念了。

基本類型和引用類型

ECMAScript變量可能包含兩種不同數據類型的值:基本類型值和引用類型值。基本類型值指的是那些保存在棧內存中的簡單數據段,即這種值完全保存在內存中的一個位置。而引用類型值是指那些保存堆內存中的對象,意思是變量中保存的實際上只是一個指針,這個指針指向內存中的另一個位置,該位置保存對象。

打個比方,基本類型和引用類型在賦值上的區別可以按“連鎖店”和“單店”來理解:基本類型賦值等于在一個新的地方安裝連鎖店的規范標準新開一個分店,新開的店與其他舊店互不相關,各自運營;而引用類型賦值相當于一個店有兩把鑰匙,交給兩個老板同時管理,兩個老板的行為都有可能對一間店的運營造成影響。

上面清晰明了的介紹了基本類型和引用類型的定義和區別。目前基本類型有:

Boolean、Null、Undefined、Number、String、Symbol,引用類型有:Object、Array、Function。之所以說“目前”,因為Symbol就是ES6才出來的,之后也可能會有新的類型出來。

再回到前面的案例,案例1中的值為基本類型,案例2中的值為引用類型。案例2中的賦值就是典型的淺拷貝,并且深拷貝與淺拷貝的概念只存在于引用類型。

深拷貝與淺拷貝

既然已經知道了深拷貝與淺拷貝的來由,那么該如何實現深拷貝?我們先分別看看Array和Object自有方法是否支持:

Array  

 

  1. var arr1 = [1, 2], arr2 = arr1.slice();  
  2. console.log(arr1); //[1, 2]  
  3. console.log(arr2); //[1, 2]  
  4. arr2[0] = 3; //修改arr2  
  5. console.log(arr1); //[1, 2]  
  6. console.log(arr2); //[3, 2] 

此時,arr2的修改并沒有影響到arr1,看來深拷貝的實現并沒有那么難嘛。我們把arr1改成二維數組再來看看:

 

  1. var arr1 = [1, 2, [3, 4]], arr2 = arr1.slice();  
  2. console.log(arr1); //[1, 2, [3, 4]]  
  3. console.log(arr2); //[1, 2, [3, 4]]  
  4. arr2[2][1] = 5;   
  5. console.log(arr1); //[1, 2, [3, 5]]  
  6. console.log(arr2); //[1, 2, [3, 5]] 

咦,arr2又改變了arr1,看來slice()只能實現一維數組的深拷貝。

具備同等特性的還有:concat、Array.from() 。

Object

1、Object.assign()

 

  1. var obj1 = {x: 1, y: 2}, obj2 = Object.assign({}, obj1);  
  2. console.log(obj1) //{x: 1, y: 2}  
  3. console.log(obj2) //{x: 1, y: 2}  
  4. obj2.x = 2; //修改obj2.x  
  5. console.log(obj1) //{x: 1, y: 2}  
  6. console.log(obj2) //{x: 2, y: 2}  
  7. var obj1 = {  
  8.     x: 1,   
  9.     y: {  
  10.         m: 1  
  11.     }  
  12. };  
  13. var obj2 = Object.assign({}, obj1);  
  14. console.log(obj1) //{x: 1, y: {m: 1}}  
  15. console.log(obj2) //{x: 1, y: {m: 1}}  
  16. obj2.y.m = 2; //修改obj2.y.m  
  17. console.log(obj1) //{x: 1, y: {m: 2}}  
  18. console.log(obj2) //{x: 2, y: {m: 2}} 

經測試,Object.assign()也只能實現一維對象的深拷貝。

2、JSON.parse(JSON.stringify(obj))

 

  1. var obj1 = {  
  2.     x: 1,   
  3.     y: {  
  4.         m: 1  
  5.     }  
  6. };  
  7. var obj2 = JSON.parse(JSON.stringify(obj1));  
  8. console.log(obj1) //{x: 1, y: {m: 1}}  
  9. console.log(obj2) //{x: 1, y: {m: 1}}  
  10. obj2.y.m = 2; //修改obj2.y.m  
  11. console.log(obj1) //{x: 1, y: {m: 1}}  
  12. console.log(obj2) //{x: 2, y: {m: 2}} 

JSON.parse(JSON.stringify(obj)) 看起來很不錯,不過MDN文檔 的描述有句話寫的很清楚:

undefined、任意的函數以及 symbol 值,在序列化過程中會被忽略(出現在非數組對象的屬性值中時)或者被轉換成 null(出現在數組中時)。

我們再來把obj1改造下:

 

  1. var obj1 = {  
  2.     x: 1,  
  3.     y: undefined,  
  4.     z: function add(z1, z2) {  
  5.         return z1 + z2  
  6.     },  
  7.     a: Symbol("foo" 
  8. };  
  9. var obj2 = JSON.parse(JSON.stringify(obj1));  
  10. console.log(obj1) //{x: 1, y: undefined, z: ƒ, a: Symbol(foo)}  
  11. console.log(JSON.stringify(obj1)); //{"x":1}  
  12. console.log(obj2) //{x: 1} 

發現,在將obj1進行JSON.stringify()序列化的過程中,y、z、a都被忽略了,也就驗證了MDN文檔的描述。既然這樣,那JSON.parse(JSON.stringify(obj))的使用也是有局限性的,不能深拷貝含有undefined、function、symbol值的對象,不過JSON.parse(JSON.stringify(obj))簡單粗暴,已經滿足90%的使用場景了。

經過驗證,我們發現JS 提供的自有方法并不能徹底解決Array、Object的深拷貝問題。只能祭出大殺器:遞歸

 

  1. function deepCopy(obj) {  
  2.     // 創建一個新對象  
  3.     let result = {}  
  4.     let keys = Object.keys(obj),  
  5.         key = null 
  6.         temp = null 
  7.     for (let i = 0; i < keys.length; i++) {  
  8.         key = keys[i];      
  9.         temp = obj[key];  
  10.         // 如果字段的值也是一個對象則遞歸操作  
  11.         if (temp && typeof temp === 'object') {  
  12.             result[key] = deepCopy(temp);  
  13.         } else {  
  14.         // 否則直接賦值給新對象  
  15.             result[key] = temp 
  16.         }  
  17.     }  
  18.     return result;  
  19.  
  20. var obj1 = {  
  21.     x: {  
  22.         m: 1  
  23.     },  
  24.     y: undefined,  
  25.     z: function add(z1, z2) {  
  26.         return z1 + z2  
  27.     },  
  28.     a: Symbol("foo" 
  29. };  
  30. var obj2 = deepCopy(obj1);  
  31. obj2.x.m = 2;  
  32. console.log(obj1); //{x: {m: 1}, y: undefined, z: ƒ, a: Symbol(foo)}  
  33. console.log(obj2); //{x: {m: 2}, y: undefined, z: ƒ, a: Symbol(foo)} 

可以看到,遞歸***的解決了前面遺留的所有問題,我們也可以用第三方庫:jquery的$.extend和lodash的_.cloneDeep來解決深拷貝。上面雖然是用Object驗證,但對于Array也同樣適用,因為Array也是特殊的Object。

到這里,深拷貝問題基本可以告一段落了。但是,還有一個非常特殊的場景:

循環引用拷貝

 

  1. var obj1 = {  
  2.     x: 1,   
  3.     y: 2  
  4. };  
  5. obj1.z = obj1;  
  6. var obj2 = deepCopy(obj1); 

此時如果調用剛才的deepCopy函數的話,會陷入一個循環的遞歸過程,從而導致爆棧。jquery的$.extend也沒有解決。解決這個問題也非常簡單,只需要判斷一個對象的字段是否引用了這個對象或這個對象的任意父級即可,修改一下代碼:

 

  1. function deepCopy(obj, parent = null) {  
  2.     // 創建一個新對象  
  3.     let result = {};  
  4.     let keys = Object.keys(obj),  
  5.         key = null 
  6.         tempnull 
  7.         _parent = parent;  
  8.     // 該字段有父級則需要追溯該字段的父級  
  9.     while (_parent) {  
  10.         // 如果該字段引用了它的父級則為循環引用  
  11.         if (_parent.originalParent === obj) {  
  12.             // 循環引用直接返回同級的新對象  
  13.             return _parent.currentParent;  
  14.         }  
  15.         _parent = _parent.parent;  
  16.     }  
  17.     for (let i = 0; i < keys.length; i++) {  
  18.         key = keys[i];  
  19.         temp= obj[key];  
  20.         // 如果字段的值也是一個對象  
  21.         if (temp && typeof temp=== 'object') {  
  22.             // 遞歸執行深拷貝 將同級的待拷貝對象與新對象傳遞給 parent 方便追溯循環引用  
  23.             result[key] = DeepCopy(temp, {  
  24.                 originalParent: obj,  
  25.                 currentParent: result,  
  26.                 parent: parent  
  27.             });  
  28.         } else { 
  29.             result[key] = temp 
  30.         }  
  31.     }  
  32.     return result;  
  33.  
  34. var obj1 = {  
  35.     x: 1,   
  36.     y: 2  
  37. };  
  38. obj1.z = obj1;  
  39. var obj2 = deepCopy(obj1);  
  40. console.log(obj1); //太長了去瀏覽器試一下吧~   
  41. console.log(obj2); //太長了去瀏覽器試一下吧~  

 

 

至此,已完成一個支持循環引用的深拷貝函數。當然,也可以使用lodash的_.cloneDeep噢~。 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2020-10-12 08:35:22

JavaScript

2021-07-16 12:33:24

Javascript深拷貝淺拷貝

2018-09-26 14:37:17

JavaScript前端編程語言

2017-08-16 13:30:05

Java深拷貝淺拷貝

2024-03-15 15:03:23

2009-05-19 17:28:44

深拷貝淺拷貝clone()

2023-05-17 08:42:46

深拷貝Golang

2025-04-27 09:45:58

JavaScript深拷貝淺拷貝

2020-06-23 08:41:47

JavaScript開發技術

2022-07-26 08:07:03

Python淺拷貝深拷貝

2021-09-27 11:07:11

深拷貝淺拷貝內存

2017-05-24 11:54:55

Javascript深拷貝

2024-04-17 09:01:08

Python深拷貝淺拷貝

2020-08-03 08:24:26

原型模式拷貝

2021-01-08 06:15:09

深拷貝淺拷貝寫時拷貝

2022-09-30 15:03:09

C語言深拷貝淺拷貝

2024-02-05 22:56:16

C++拷貝開發

2023-05-17 07:36:00

淺拷貝深拷貝對象

2023-09-22 12:21:33

Python深拷貝淺拷貝

2023-05-08 09:00:46

JSON深拷貝對象
點贊
收藏

51CTO技術棧公眾號

亚洲欧洲中文天堂| 婷婷综合五月天| 91亚色免费| 日韩欧美视频在线免费观看| 久久99高清| 欧美另类变人与禽xxxxx| 欧美大片免费播放| 天堂а√在线8种子蜜桃视频| 亚洲三级观看| 中文字幕亚洲一区在线观看| 亚洲精品成人无码毛片| 久久免费公开视频| 日韩一区二区三区在线看| 婷婷中文字幕一区三区| 亚洲一区二区在线看| 蜜桃av噜噜一区二区三区麻豆| 国产精品综合| 欧美成人午夜剧场免费观看| 女~淫辱の触手3d动漫| av日韩在线免费观看| 欧美日韩免费看| 91精品国产吴梦梦| 懂色av中文在线| www.亚洲人| 91精品啪aⅴ在线观看国产| 久久国产黄色片| 综合日韩在线| www.久久久久久.com| 日本xxxx裸体xxxx| 91嫩草精品| 911精品国产一区二区在线| 日韩免费毛片视频| 国内在线免费视频| 亚洲天堂2014| 亚洲综合第一| 国产乱子伦三级在线播放| 99精品久久99久久久久| 不卡视频一区| 99久久国产免费| 青青草国产精品97视觉盛宴| 秋霞成人午夜鲁丝一区二区三区| 欧美一级高潮片| 中文字幕av亚洲精品一部二部| 国产亚洲欧洲在线| www.色天使| 亚洲专区视频| 精品香蕉在线观看视频一| 国产精品一区二区在线免费观看| 日韩三级不卡| 91精品久久久久久久99蜜桃 | 欧美精品 国产精品| 日av中文字幕| 欧美黑人粗大| 在线免费av一区| 久久久久久久激情| 午夜影院在线播放| 韩曰欧美视频免费观看| 免费看的黄色大片| 亚洲天堂导航| 色综合久久久久综合99| 日本成年人网址| 亚洲欧洲自拍| 在线观看一区日韩| 人人爽人人av| 成人黄色免费观看| 91成人网在线| 中文字幕亚洲影院| 国产在线不卡一区二区三区| 欧美一区二区不卡视频| 欧美熟妇另类久久久久久多毛| 国产免费区一区二区三视频免费 | 高h震动喷水双性1v1| 国产精品一区二区久激情瑜伽| 亚洲在线免费视频| 成人黄色在线观看视频| 成人97人人超碰人人99| 精品伊人久久大线蕉色首页| 日本一区视频| 国产精品欧美一级免费| 国产一二三四区在线观看| 青青在线视频| 欧美性猛交xxxx| 簧片在线免费看| 精品国产亚洲一区二区三区| 亚洲第一区在线观看| 无码 人妻 在线 视频| 久久理论电影| 久久久爽爽爽美女图片| 日本免费精品视频| 国产一区二区三区黄视频| 国产精品成人一区二区三区| 欧洲毛片在线| 亚洲男帅同性gay1069| 日韩网站在线免费观看| 日韩三区在线| 日韩免费观看高清完整版| 四虎永久免费影院| 99九九热只有国产精品| 久久免费视频观看| 中文字幕日产av| 国产美女视频一区| 日韩电影在线播放| 日韩影视在线| 欧美在线free| 久久性爱视频网站| 久久激情电影| 97av在线影院| 国产色视频在线| 国产丝袜欧美中文另类| 亚洲精品天堂成人片av在线播放 | 日韩欧美有码在线| 国产又粗又猛又爽又黄| 精品大片一区二区| 久久久影视精品| 在线观看不卡的av| 91在线观看高清| 免费日韩在线观看| 色综合视频一区二区三区日韩| 亚洲国产精品国自产拍av秋霞| 国产精品情侣呻吟对白视频| 在线日韩欧美| 2019国产精品视频| 天堂а√在线官网| 色婷婷亚洲精品| 一级黄色免费视频| 欧美福利在线| 91免费在线视频网站| 懂色av中文在线| 日韩欧美中文字幕在线观看| 老熟女高潮一区二区三区| 久久激情电影| 国产精品视频精品视频| 三级毛片在线免费看| 亚洲成人资源网| 老熟女高潮一区二区三区| 先锋资源久久| 91精品国产综合久久男男| 噜噜噜在线观看播放视频| 激情亚洲一区二区三区四区| 国产裸体视频网站| 女主播福利一区| 亚洲一区二区三区四区在线播放| 国产精品一区在线看| 欧美性高潮在线| 无码人妻精品一区二区三应用大全| 亚洲激精日韩激精欧美精品| www.久久久| 美女精品导航| 欧美一区二区三区视频免费 | 欧美最顶级的aⅴ艳星| 成人免费公开视频| 亚洲最大色网站| 久久发布国产伦子伦精品| 欧美日韩调教| 国产精品免费区二区三区观看 | 国产999在线观看| 日本天堂在线| 欧美性淫爽ww久久久久无| 中文幕无线码中文字蜜桃| 国产精品嫩草99av在线| 欧美激情视频一区二区三区| 欧美日韩电影免费看| 亚洲一区二区久久久| 亚洲香蕉在线视频| **性色生活片久久毛片| 永久免费看片在线观看| 亚洲人体大胆视频| 乱色588欧美| 另类中文字幕国产精品| 日韩有码在线视频| 国产视频一区二区三区四区五区 | 国产精品一区二区三区四| 久久精品在线观看| 日本黄大片一区二区三区| 婷婷综合伊人| 国产伦精品一区二区三区四区视频| 欧美大胆a人体大胆做受| 亚洲天堂精品在线| 国产精品久久久久久久久久久久久久久久久久 | 精品久久久久久久久久久久久久久久久久| 成人黄色av电影| 国产黄色一级网站| 日本一区二区在线看| 91精品国产一区二区三区动漫| sm在线播放| 尤物精品国产第一福利三区 | 日本三级一区| 这里只有精品在线观看| 成人毛片在线精品国产| 在线精品视频小说1| 五月天婷婷色综合| 91视视频在线观看入口直接观看www| 99久久久无码国产精品6| 婷婷综合社区| 开心色怡人综合网站| 亚洲美女色播| 欧美在线视频网站| 麻豆tv入口在线看| 亚洲精品小视频在线观看| 一级黄色小视频| 精品久久久久国产| 亚洲一级生活片| 久久久久高清精品| 在线免费黄色小视频| 视频精品一区二区| 国产乱子伦精品无码专区| 精品九九在线| 精品亚洲欧美日韩| 国产成人免费av一区二区午夜| 2023亚洲男人天堂| 色www永久免费视频首页在线| 夜夜嗨av一区二区三区免费区| 精品人妻一区二区三区麻豆91| 91国模大尺度私拍在线视频| 九九热国产在线| 国产精品丝袜91| 日批在线观看视频| 国产麻豆精品在线| 激情五月俺来也| 性久久久久久| 黄色大片中文字幕| 中文精品久久| 中文字幕一区二区三区有限公司| 欧美久久精品| 国产精品久久久久久久小唯西川 | fc2ppv国产精品久久| 亚洲视频在线免费观看| 外国精品视频在线观看 | 少妇无码av无码专区在线观看 | 99热在线观看免费精品| 一区二区三区中文在线观看| 久久精品在线观看视频| 久久亚洲综合色一区二区三区 | 国产日韩精品一区二区三区| 少妇伦子伦精品无吗| 精品在线观看视频| 99sesese| 麻豆一区二区在线| 天堂网在线免费观看| 蜜桃av噜噜一区二区三区小说| caoporn超碰97| 久久亚洲精选| www日韩视频| 日韩电影免费在线| 亚洲精品视频导航| 男女视频一区二区| 日韩av片专区| 国产在线观看免费一区| 日本一区二区三区在线免费观看| 激情av综合网| 无码人妻少妇色欲av一区二区| 国产制服丝袜一区| 日本亚洲一区二区三区| 国产69精品久久777的优势| 日韩av成人网| 不卡的av电影在线观看| 一区二区免费在线观看视频| 99国产精品久久久久| 波多野结衣福利| 国产女人aaa级久久久级 | 天堂av在线播放| 亚洲欧美日本另类| www.中文字幕久久久| 久久亚洲精品网站| 免费电影视频在线看| 国内精品久久久久伊人av | 欧美色道久久88综合亚洲精品| 黄色免费av网站| 欧美三级韩国三级日本一级| 国产一区二区三区四区视频 | 97中文字幕在线观看| 99久久国产免费看| 国产熟妇久久777777| 国产精品久久久久久亚洲伦| 91精品国产闺蜜国产在线闺蜜| 一区二区三区欧美亚洲| 日韩不卡视频在线| 欧美剧在线免费观看网站 | 久久亚洲人体| 99久久精品免费看国产一区二区三区 | 国产wwwxx| 国产乱码一区二区三区| 成人在线电影网站| 国产日韩欧美一区二区三区乱码| 五月婷婷婷婷婷| 一区二区三区在线视频免费| 91精品国产乱码久久久张津瑜| 日本久久电影网| 国产99久久九九精品无码免费| 亚洲精品99久久久久| avtt在线播放| 97国产真实伦对白精彩视频8| 黄色精品视频| 国产精品久久久久免费| 色欧美自拍视频| 国产午夜福利在线播放| 老司机免费视频一区二区| 农村末发育av片一区二区| 国产三级精品视频| 九九久久免费视频| 欧美视频日韩视频在线观看| 成人av无码一区二区三区| 一区二区三区国产视频| 91福利在线尤物| 91精品国产综合久久香蕉| 亚洲盗摄视频| 欧美中日韩在线| 激情综合色综合久久| 中文字幕丰满孑伦无码专区| 最新久久zyz资源站| 久久夜色精品国产噜噜亚洲av| 欧美一级黄色片| 亚洲xxxxxx| 日韩av高清不卡| 牛牛视频精品一区二区不卡| 青青视频免费在线观看| 青青草伊人久久| 91网站免费入口| 天天av天天翘天天综合网色鬼国产| 97人妻精品一区二区三区| 亚洲片av在线| 一区二区三区短视频| 国产精品视频入口| 91av精品| 午夜宅男在线视频| 国产丝袜欧美中文另类| 黄色一级片免费在线观看| 精品久久久久久无| av免费在线观看网址| 国产欧美日韩专区发布| 精品国产一区二区三区香蕉沈先生| 国产特级黄色大片| 成人亚洲一区二区一| 九九视频免费看| 日韩无一区二区| 成人福利网站| 91在线|亚洲| 国产精品88久久久久久| 色免费在线视频| 国产精品人妖ts系列视频| 色老头一区二区| 亚洲天堂成人在线| www成人在线视频| 日韩免费三级| 日韩高清不卡一区二区三区| 国精产品一区二区三区| 一本大道久久精品懂色aⅴ| 四虎精品在线| 国产黑人绿帽在线第一区| 国产中文字幕一区二区三区| 无遮挡又爽又刺激的视频| 久久美女高清视频| 欧美一区免费看| 在线观看欧美日韩| 另类一区二区三区| 四虎免费在线观看视频| 国产精品77777| 国产无遮无挡120秒| 日韩av在线免费播放| 裤袜国产欧美精品一区| 色综合久久88色综合天天提莫| 日韩精品亚洲一区| www.99re6| 精品女同一区二区| 日本在线啊啊| 亚洲第一导航| 国产老肥熟一区二区三区| 国产精品成人免费一区二区视频| 亚洲国产天堂久久综合网| 欧美性猛交xxx高清大费中文| 色爱区成人综合网| 国产一区二区电影| 日本熟妇乱子伦xxxx| 亚洲欧美制服综合另类| 久久麻豆视频| 五月丁香综合缴情六月小说| 2021久久国产精品不只是精品| 久久久久亚洲视频| 久久伊人精品天天| 国产一级成人av| 超碰在线97免费| 亚洲图片有声小说| 国产对白叫床清晰在线播放| 亚洲自拍偷拍视频| 一区二区三区导航| 美女视频久久久| 亚洲黄色有码视频| 先锋影音一区二区| 黄色www网站| 国产精品麻豆久久久| 六月丁香综合网| 国产精品天天狠天天看 | 免费无码av片在线观看| 国产精品美女一区二区三区| 亚洲伦理在线观看| 国产精品视频色| 国产一区导航| 我家有个日本女人| 亚洲香蕉伊综合在人在线视看| 一区二区三区视频播放|