国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Javascript的對象拷貝

開發 前端
在開始之前,我先普及一些基礎知識。Javascript 的對象只是指向內存中某個位置的指針。這些指針是可變的,也就是說,它們可以重新被賦值。

[[391560]]

在開始之前,我先普及一些基礎知識。Javascript 的對象只是指向內存中某個位置的指針。這些指針是可變的,也就是說,它們可以重新被賦值。所以僅僅復制這個指針,其結果是有兩個指針指向內存中的同一個地址。

  1. var foo = { 
  2.     a : "abc" 
  3. console.log(foo.a); 
  4. // abc 
  5.  
  6. var bar = foo
  7. console.log(bar.a); 
  8. // abc 
  9.  
  10. foo.a = "yo foo"
  11. console.log(foo.a); 
  12. // yo foo 
  13. console.log(bar.a); 
  14. // yo foo 
  15.  
  16. bar.a = "whatup bar?"
  17. console.log(foo.a); 
  18. // whatup bar? 
  19. console.log(bar.a); 
  20. // whatup bar?     

通過上面的例子可以看到,對象 foo 和 bar 都能隨著對方的變化而變化。所以在拷貝 Javascript 中的對象時,要根據實際情況做一些考慮。

淺拷貝

如果要操作的對象擁有的屬性都是值類型,那么可以使用擴展語法或 Object.assign(...)

  1. var obj = { foo: "foo", bar: "bar" }; 
  2. var copy = { ...obj }; 
  3. // Object { foo: "foo", bar: "bar" } 
  4. var obj = { foo: "foo", bar: "bar" }; 
  5. var copy = Object.assign({}, obj); 
  6. // Object { foo: "foo", bar: "bar" } 

可以看到上面兩種方法都可以把多個不同來源對象中的屬性復制到一個目標對象中。

  1. var obj1 = { foo: "foo" }; 
  2. var obj2 = { bar: "bar" }; 
  3. var copySpread = { ...obj1, ...obj2 }; 
  4. // Object { foo: "foo", bar: "bar" } 
  5. var copyAssign = Object.assign({}, obj1, obj2); 
  6. // Object { foo: "foo", bar: "bar" } 

上面這種方法是存在問題的,如果對象的屬性也是對象,那么實際被拷貝的只是那些指針,這跟執行 var bar = foo; 的效果是一樣的,和第一段代碼中的做法一樣。

  1. var foo = { a: 0 , b: { c: 0 } }; 
  2. var copy = { ...foo }; 
  3. copy.a = 1
  4. copy.b.c = 2
  5. console.dir(foo); 
  6. // { a: 0, b: { c: 2 } } 
  7. console.dir(copy); 
  8. // { a: 1, b: { c: 2 } } 

深拷貝(有限制)

想要對一個對象進行深拷貝,一個可行的方法是先把對象序列化為字符串,然后再對它進行反序列化。

  1. var obj = { a: 0, b: { c: 0 } }; 
  2. var copy = JSON.parse(JSON.stringify(obj)); 

不幸的是,這個方法只在對象中包含可序列化值,同時沒有循環引用的情況下適用。常見的不能被序列化的就是日期對象 —— 盡管它顯示的是字符串化的 ISO 日期格式,但是 JSON.parse 只會把它解析成為一個字符串,而不是日期類型。

深拷貝 (限制較少)

對于一些更復雜的場景,我們可以用 HTML5 提供的一個名為結構化克隆的新算法。不過,截至本文發布為止,有些內置類型仍然無法支持,但與 JSON.parse 相比較而言,它支持的類型要多的多:Date、RegExp、 Map、 Set、 Blob、 FileList、 ImageData、 sparse 和 typed Array。它還維護了克隆對象的引用,這使它可以支持循環引用結構的拷貝,而這些在前面所說的序列化中是不支持的。

目前還沒有直接調用結構化克隆的方法,但是有些新的瀏覽器特性的底層用了這個算法。所以深拷貝對象可能需要依賴一系列的環境才能實現。

Via MessageChannels: 其原理是借用了通信中用到的序列化算法。由于它是基于事件的,所以這里的克隆也是一個異步操作。

  1. class StructuredCloner { 
  2.   constructor() { 
  3.     this.pendingClones_ = new Map(); 
  4.     this.nextKey_ = 0
  5.  
  6.     const channel = new MessageChannel(); 
  7.     this.inPort_ = channel.port1; 
  8.     this.outPort_ = channel.port2; 
  9.  
  10.     this.outPort_.onmessage = ({data: {key, value}}) => { 
  11.       const resolve = this.pendingClones_.get(key); 
  12.       resolve(value); 
  13.       this.pendingClones_.delete(key); 
  14.     }; 
  15.     this.outPort_.start(); 
  16.   } 
  17.  
  18.   cloneAsync(value) { 
  19.     return new Promise(resolve => { 
  20.       const key = this.nextKey_++; 
  21.       this.pendingClones_.set(key, resolve); 
  22.       this.inPort_.postMessage({key, value}); 
  23.     }); 
  24.   } 
  25.  
  26. const structuredCloneAsync = window.structuredCloneAsync = 
  27.     StructuredCloner.prototype.cloneAsync.bind(new StructuredCloner); 
  28.  
  29. const main = async () => { 
  30.   const original = { date: new Date(), number: Math.random() }; 
  31.   originaloriginal.self = original; 
  32.  
  33.   const clone = await structuredCloneAsync(original); 
  34.  
  35.   // different objects: 
  36.   console.assert(original !== clone); 
  37.   console.assert(original.date !== clone.date); 
  38.  
  39.   // cyclical: 
  40.   console.assert(original.self === original); 
  41.   console.assert(clone.self === clone); 
  42.  
  43.   // equivalent values: 
  44.   console.assert(original.number === clone.number); 
  45.   console.assert(Number(original.date) === Number(clone.date)); 
  46.  
  47.   console.log("Assertions complete."); 
  48. }; 
  49.  
  50. main(); 

Via the history API:history.pushState() 和 history.replaceState()都會給它們的第一個參數做一個結構化克隆!需要注意的是,此方法是同步的,因為對瀏覽器歷史記錄進行操作的速度不是很快,假如頻繁調用這個方法,將會導致瀏覽器卡死。

  1. const structuredClone = obj => { 
  2.   const oldState = history.state; 
  3.   history.replaceState(obj, null); 
  4.   const clonedObj = history.state; 
  5.   history.replaceState(oldState, null); 
  6.   return clonedObj; 
  7. }; 

Via notification API:當創建一個 notification 實例的時候,構造器為它相關的數據做了結構化克隆。需要注意的是,它會嘗試向用戶展示瀏覽器通知,但是除非它收到了用戶允許展示通知的請求,否則它什么都不會做。一旦用戶點擊同意的話,notification 會立刻被關閉。

  1. const structuredClone = obj => { 
  2.   const n = new Notification("", {data: obj, silent: true}); 
  3.   nn.onshow = n.close.bind(n); 
  4.   return n.data; 
  5. }; 

用 Node.js 進行深拷貝

Node.js 的 8.0.0 版本提供了一個 序列化 api 可以和結構化克隆相媲美. 不過這個 API 在本文發布的時候,還只是被標記為試驗性的:

  1. const v8 = require('v8'); 
  2. const buf = v8.serialize({a: 'foo', b: new Date()}); 
  3. const cloned = v8.deserialize(buf); 
  4. cloned.b.getMonth(); 

在 8.0.0 版本以下比較穩定的方法,可以考慮用 lodash 的 cloneDeep函數,它的思想多少也基于結構化克隆算法。

結論

Javascript 中最好的對象拷貝的算法,很大程度上取決于其使用環境,以及你需要拷貝的對象類型。雖然 lodash 是最安全的泛型深拷貝函數,但是如果你自己封裝的話,也許能夠獲得效率更高的實現方法,以下就是一個簡單的深拷貝,對 Date 日期對象也同樣適用:

  1. function deepClone(obj) { 
  2.   var copy; 
  3.  
  4.   // Handle the 3 simple types, and null or undefined 
  5.   if (null == obj || "object" != typeof obj) return obj; 
  6.  
  7.   // Handle Date 
  8.   if (obj instanceof Date) { 
  9.     copy = new Date(); 
  10.     copy.setTime(obj.getTime()); 
  11.     return copy; 
  12.   } 
  13.  
  14.   // Handle Array 
  15.   if (obj instanceof Array) { 
  16.     copy = []; 
  17.     for (var i = 0len = obj.length; i < len; i++) { 
  18.         copy[i] = deepClone(obj[i]); 
  19.     } 
  20.     return copy; 
  21.   } 
  22.  
  23.   // Handle Function 
  24.   if (obj instanceof Function) { 
  25.     copy = function() { 
  26.       return obj.apply(this, arguments); 
  27.     } 
  28.     return copy; 
  29.   } 
  30.  
  31.   // Handle Object 
  32.   if (obj instanceof Object) { 
  33.       copy = {}; 
  34.       for (var attr in obj) { 
  35.           if (obj.hasOwnProperty(attr)) copy[attr] = deepClone(obj[attr]); 
  36.       } 
  37.       return copy; 
  38.   } 
  39.  
  40.   throw new Error("Unable to copy obj as type isn't supported " + obj.constructor.name); 

我很期待可以隨便使用結構化克隆的那一天的到來,讓對象拷貝不再令人頭疼^_^

 

責任編輯:趙寧寧 來源: 前端先鋒
相關推薦

2025-04-27 09:45:58

JavaScript深拷貝淺拷貝

2024-08-02 08:43:24

JavaScript開發者工具箱深拷貝

2021-07-16 12:33:24

Javascript深拷貝淺拷貝

2017-05-24 11:54:55

Javascript深拷貝

2020-10-12 08:35:22

JavaScript

2018-09-26 14:37:17

JavaScript前端編程語言

2022-09-26 09:01:23

JavaScript淺拷貝深拷貝

2018-05-10 14:20:18

前端JavaScript深拷貝

2021-05-14 00:00:15

JavaScript開發代碼

2023-05-08 09:00:46

JSON深拷貝對象

2020-06-23 08:41:47

JavaScript開發技術

2023-05-12 08:11:58

JavaScriptJSON克隆

2024-01-29 00:57:20

GuavaJava拷貝

2021-07-27 22:56:00

JavaScript編程開發

2023-05-16 07:35:29

2021-10-21 18:47:37

JavaScript面向對象

2023-05-05 08:47:35

Java淺拷貝深拷貝

2011-07-01 10:52:49

C++構造函數賦值操作

2012-07-25 13:25:11

ibmdw

2020-08-23 11:32:21

JavaScript開發技術
點贊
收藏

51CTO技術棧公眾號

日本欧美大码aⅴ在线播放| 久久香蕉综合色| 欧美xxx久久| 婷婷av在线| 久久久久久久97| 性久久久久久| 欧美日韩第二页| 欧美一区二区三区视频免费播放| 亚洲专区视频| 国产视频手机在线播放| 中文字幕日韩欧美在线视频| 日韩电影免费一区| 视频在线这里都是精品| 久久亚裔精品欧美| 欧美制服丝袜第一页| 五月天久久久| 色婷婷亚洲十月十月色天| 欧美日韩国产综合新一区| 你懂的视频在线| 4388成人网| 精品制服美女丁香| 污版视频在线观看| 在线观看国产精品日韩av| 99久久亚洲精品| 国产欧美精品aaaaaa片| 黑人巨大精品欧美一区二区一视频 | 日韩国产欧美一区二区三区| 狠狠色伊人亚洲综合网站l| 日韩情涩欧美日韩视频| 欧美xxx网站| 尤物九九久久国产精品的分类| 成人午夜sm精品久久久久久久| 国产一区二区三区高清在线观看| 波多野结衣在线一区二区| 手机在线看福利| 成人欧美一区二区三区黑人孕妇 | 亚瑟国产精品| 欧美一级欧美一级在线播放| 欧美日韩一区在线观看视频| 青草av在线| 亚洲欧美一区二区不卡| 欧美激情视频一区二区三区| 一区二区三区韩国免费中文网站| 精品综合久久| 日产国产欧美视频一区精品| 成人福利在线观看| 日本午夜一区二区| 韩国日本美国免费毛片| 精品一区二区三区在线观看国产| 欧美激情手机在线视频 | 丝袜美腿一区| 一区二区三区小说| www成人免费| 91麻豆成人久久精品二区三区| 91欧美精品午夜性色福利在线 | 成人中文字幕+乱码+中文字幕| 国产免费av国片精品草莓男男| 极品少妇xxxx精品少妇偷拍| 98精品在线视频| 国产日韩精品在线看| 日韩午夜在线电影| 国产日韩欧美影视| 久久精品国产亚洲夜色av网站| 狠狠久久伊人| 欧美精品在线观看一区二区| 国产一区二区三区精彩视频 | www久久日com| 久久综合久久八八| 国产盗摄女厕一区二区三区| 免费在线观看污视频| 国产精品r级在线| 男女污污的视频| 欧美综合一区第一页| 亚洲欧美一区二区三区情侣bbw| 亚洲成av人在线观看| 激情欧美一区二区| 亚洲精品孕妇| 欧美91精品| 秋霞午夜一区二区三区视频| av国产在线观看| av日韩在线免费| 日韩精品第一页| 亚洲日本无吗高清不卡| 国产精品网站视频| 亚洲欧美国产精品专区久久| 日韩一级成人av| 日韩欧美亚洲国产精品字幕久久久| 黑人巨大精品欧美一区| 99亚洲乱人伦aⅴ精品| 国产一级网站视频在线| 日韩视频在线免费播放| 91精品视频网站| 中文字幕日韩精品有码视频| 欧美性大战久久| 国产精品麻豆欧美日韩ww| 成人午夜视频福利| 日韩avvvv在线播放| 第四色成人网| 欧美日韩麻豆| 超碰超碰人人人人精品| 小水嫩精品福利视频导航| 开心丁香婷婷深爱五月 | 国产精品久久久久久久久久久久久久久| av在线免费观看国产| 精品视频在线看| 日韩专区一卡二卡| 日本亚洲一区| 蜜桃一级网站.| 日本电影在线观看| 欧洲美女日日| 99国产精品国产精品久久| 91精品福利视频| 好吊一区二区三区| 日韩欧美视频免费在线观看| 五月综合激情婷婷六月色窝| 久久99国产精品久久99大师| 欧美一级片中文字幕| 亚洲男人天堂网站| 成人激情视频网站| 欧美激情偷拍自拍| aaa大片在线观看| 欧美一级中文字幕| 91精品啪在线观看国产60岁| 国产99久久久精品| 色88888久久久久久影院| 七七成人影院| av免费中文字幕| 欧美极品美女电影一区| 国产一区二区在线观看视频| 北条麻妃在线视频| 国内伊人久久久久久网站视频| 久久精品三级| 成人开心激情| 奇米一区二区三区四区久久| 日韩成人伦理电影在线观看| 欧美12一14sex性hd| 久久99国产精品| 91久久嫩草影院一区二区| 欧美中文字幕一区二区三区| 91在线精品一区二区| 欧美fxxxxxx另类| 麻豆网站在线免费观看| 奇米4444一区二区三区| 国产精品一区一区三区| avtt久久| 国产wwwxx| 成人激情av在线| 亚洲人成五月天| 91网站在线播放| 日韩精品三级| 在线资源av| 色综合久久久久久中文网| 国产三级欧美三级| 免费成人结看片| 激情小视频在线| 欧美男女交配视频| 18视频在线观看娇喘| 波多野结衣之无限发射| 久久综合九色综合88i| 三上悠亚一区| 男人天堂手机在线| 涩涩涩在线视频| 在线午夜精品自拍| 欧美久久精品午夜青青大伊人| 福利视频久久| gogo高清免费视频| 久久久91麻豆精品国产一区| 一本不卡影院| 色综合天天综合色综合av| 久久久亚洲影院| 国产精品50p| 精品国产乱码一区二区三区| 精品一区二区三区在线播放| 欧美mv和日韩mv的网站| 国产精品毛片一区视频| 美丽的姑娘在线观看免费动漫| 日韩精品1区| 中文字幕亚洲视频| 欧美多人爱爱视频网站| 人人妻人人添人人爽欧美一区| 美女永久在线网站| 中文字幕成在线观看| 国产日韩欧美高清免费| 亚洲男人天堂一区| 久久九九精品99国产精品| 亚洲自拍偷拍一区| 成人黄色免费| 日本午夜精品| 久久久久成人黄色影片| 亚洲精品日韩久久久| 亚洲 高清 成人 动漫| 亚洲精品毛片| 99视频精品免费视频| 精品国产电影一区二区| 亚洲一区免费看| 成人影院av| 国产在线播精品第三| 91精品国产91久久久久久最新毛片 | 亚洲自拍av在线| 久久久久久九九|