<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          太卷了!瀏覽器也支持原生的深拷貝API了?

          共 2826字,需瀏覽 6分鐘

           ·

          2021-12-24 21:08

          大家好,我是 ConardLi,今天來聊一個前端老生常談的話題,深拷貝。

          在以前,由于瀏覽器并未對這個能力提供原生支持,所以它經(jīng)常出現(xiàn)在 手寫XXX 這樣的面試題中,我之前也為它專門寫過一篇文章:

          如何寫出一個驚艷面試官的深拷貝

          不過,我們成功的把瀏覽器給卷了,現(xiàn)在它給我們提供了一個原生的深拷貝 API:structuredClone。

          淺拷貝

          再看深拷貝之前,我們還是先來簡單回顧一下淺拷貝和深拷貝的區(qū)別(不要嫌我啰嗦,主要為了照顧新手同學,如果有基礎的同學直接跳過)。

          • 淺拷貝:創(chuàng)建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果屬性是引用類型,拷貝的就是內(nèi)存地址 ,所以如果其中一個對象改變了這個地址,就會影響到另一個對象。
          • 將一個對象從內(nèi)存中完整的拷貝一份出來,從堆內(nèi)存中開辟一個新的區(qū)域存放新對象,且修改新對象不會影響原對象。

          在代碼里我們復制一個對象可能用的最多的就是擴展運算符 ...,這就是一種淺拷貝。

          const?myOriginal?=?{
          ??someProp:?"code秘密花園",
          ??anotherProp:?{
          ????withAnotherProp:?1,
          ????andAnotherProp:?true
          ??}
          };

          const?myShallowCopy?=?{...myOriginal};

          我們直接在淺拷貝對象上添加或更改屬性只會影響拷貝副本,而不會影響原始值:

          myShallowCopy.aNewProp?=?"ConardLi";
          console.log(myOriginal.aNewProp)
          //?^?logs?`undefined`

          如果我們更改之前的引用對象屬性,副本和原始值雙方都會影響:

          myShallowCopy.anotherProp.aNewProp?=?"ConardLi";
          console.log(myOriginal.anotherProp.aNewProp)?
          //?^?logs?`ConardLi`

          本質(zhì)上,就是拷貝對原始類型(string、number、bigint、boolean、undefined、symbol、null)和引用類型(object、array 等)的處理不一樣,這倆的區(qū)別,可以看看這篇文章,這里就不過多展開了。

          【JS進階】你真的掌握變量和類型了嗎

          深拷貝

          與淺拷貝相對的就是深拷貝,深拷貝算法也會一個一個地拷貝一個對象的屬性,但是當它拷貝對另一個對象的引用時會遞歸調(diào)用,同時創(chuàng)建該引用類型的一個副本,這可以有效避免我們在代碼里共享一個意想不到的對象引用。

          在以前,我們需要依賴一些第三方庫來實現(xiàn)深拷貝,比如 LodashcloneDeep() 函數(shù),或者可能大多數(shù)人用的基于是 JSONhack

          const?myDeepCopy?=?JSON.parse(JSON.stringify(myOriginal));

          但是這種方法缺點很多:

          • 循環(huán)引用:JSON.stringify() 的對象中如果有循環(huán)引用會拋出異常 Converting circular structure to JSON
          • 其他數(shù)據(jù)類型:JSON.stringify() 無法拷貝 Map、Set、RegExp 這些特殊數(shù)據(jù)類型。
          • 函數(shù):JSON.stringify() 會默認移除函數(shù)。

          structuredClone

          現(xiàn)在,structuredClone API 已經(jīng)成為了一個 HTML 規(guī)范中的標準提案,用它可以輕松實現(xiàn)一個深拷貝,并且也默認解決了循環(huán)引用等問題、支持了很多默認的數(shù)據(jù)類型。

          //?Create?an?object?with?a?value?and?a?circular?reference?to?itself.
          const?original?=?{?name:?"MDN"?};
          original.itself?=?original;

          //?Clone?it
          const?clone?=?structuredClone(original);

          console.assert(clone?!==?original);?//?the?objects?are?not?the?same?(not?same?identity)
          console.assert(clone.name?===?"MDN");?//?they?do?have?the?same?values
          console.assert(clone.itself?===?clone);?//?and?the?circular?reference?is?preserved

          并且,相比 JSON.parse()structuredClone API 的性能更好,特別是在處理一些更大復雜的對象的時候,所以我們可以用它來作為代碼里深拷貝的默認方法啦,為了兼容性考慮,可以用 JSON.stringify 或者其他工具函數(shù)作為備用。

          不過,這個 API 也并不完美,它也有些缺點:

          • 原型:無法拷貝對象的原型鏈。
          • 函數(shù):無法拷貝函數(shù)。
          • 不可克隆:并沒有支持所有類型的拷貝,比如 Error。

          當然,大部分實際的需求場景中,我們沒必要拷貝這些東西,估計這些也就只能出現(xiàn)在面試題里面了。。。先看怎么做的話,還是可以回去看我這篇文章:如何寫出一個驚艷面試官的深拷貝

          兼容性

          目前,主流瀏覽器(Chrome、Firefox、Safari)都已經(jīng)在 release 版本支持了這個 APIFirefox 也已經(jīng)在其 94 穩(wěn)定版本支持了。

          另外,Node 17Deno 1.14 也已經(jīng)實現(xiàn)了這個 API,未來一定會成為一個被廣泛使用的 API 的,你可以放心大膽的用了。

          參考

          • https://caniuse.com/?search=structuredClone
          • https://web.dev/structured-clone/


          往期推薦



          解密初、中、高級程序員的進化之路(前端)


          程序員一定會有35歲危機嗎?


          近 20k Star的項目說不做就不做了,但總結的內(nèi)容值得借鑒


          但凡早知道這28個網(wǎng)站,都不至于學得那么不扎實





          如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:

          1. 點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-)

          2. 歡迎加我微信「huab119」拉你進技術群,長期交流學習...

            關注公眾號「前端勸退師」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。



          點個在看支持我吧,轉發(fā)就更好了

          如果覺得這篇文章還不錯,來個【轉發(fā)、收藏、在看】三連吧,讓更多的人也看到~


          瀏覽 60
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美一区二区三区18 | aa在线免费观看 | 亚洲视频91 | 成人做爰黄70片免费 | 囯产精品久久久久久久久久久久 |