摘要:專題系列第六篇,講解深淺拷貝的技巧和以及實現深淺拷貝的思路前言拷貝也是面試經典吶數組的淺拷貝如果是數組,我們可以利用數組的一些方法比如返回一個新數組的特性來實現拷貝。所以我們可以看出使用和是一種淺拷貝。
前言JavaScript 專題系列第六篇,講解深淺拷貝的技巧和以及實現深淺拷貝的思路
拷貝也是面試經典吶!
數組的淺拷貝如果是數組,我們可以利用數組的一些方法比如:slice、concat 返回一個新數組的特性來實現拷貝。
比如:
var arr = ["old", 1, true, null, undefined]; var new_arr = arr.concat(); new_arr[0] = "new"; console.log(arr) // ["old", 1, true, null, undefined] console.log(new_arr) // ["new", 1, true, null, undefined]
用 slice 可以這樣做:
var new_arr = arr.slice();
但是如果數組嵌套了對象或者數組的話,比如:
var arr = [{old: "old"}, ["old"]]; var new_arr = arr.concat(); arr[0].old = "new"; arr[1][0] = "new"; console.log(arr) // [{old: "new"}, ["new"]] console.log(new_arr) // [{old: "new"}, ["new"]]
我們會發現,無論是新數組還是舊數組都發生了變化,也就是說使用 concat 方法,克隆的并不徹底。
如果數組元素是基本類型,就會拷貝一份,互不影響,而如果是對象或者數組,就會只拷貝對象和數組的引用,這樣我們無論在新舊數組進行了修改,兩者都會發生變化。
我們把這種復制引用的拷貝方法稱之為淺拷貝,與之對應的就是深拷貝,深拷貝就是指完全的拷貝一個對象,即使嵌套了對象,兩者也相互分離,修改一個對象的屬性,也不會影響另一個。
所以我們可以看出使用 concat 和 slice 是一種淺拷貝。
數組的深拷貝那如何深拷貝一個數組呢?這里介紹一個技巧,不僅適用于數組還適用于對象!那就是:
var arr = ["old", 1, true, ["old1", "old2"], {old: 1}] var new_arr = JSON.parse( JSON.stringify(arr) ); console.log(new_arr);
是一個簡單粗暴的好方法,就是有一個問題,不能拷貝函數,我們做個試驗:
var arr = [function(){ console.log(a) }, { b: function(){ console.log(b) } }] var new_arr = JSON.parse(JSON.stringify(arr)); console.log(new_arr);
我們會發現 new_arr 變成了:
淺拷貝的實現以上三個方法 concat、slice、JSON.stringify 都算是技巧類,可以根據實際項目情況選擇使用,接下來我們思考下如何實現一個對象或者數組的淺拷貝。
想一想,好像很簡單,遍歷對象,然后把屬性和屬性值都放在一個新的對象不就好了~
嗯,就是這么簡單,注意幾個小點就可以了:
var shallowCopy = function(obj) { // 只拷貝對象 if (typeof obj !== "object") return; // 根據obj的類型判斷是新建一個數組還是對象 var newObj = obj instanceof Array ? [] : {}; // 遍歷obj,并且判斷是obj的屬性才拷貝 for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = obj[key]; } } return newObj; }深拷貝的實現
那如何實現一個深拷貝呢?說起來也好簡單,我們在拷貝的時候判斷一下屬性值的類型,如果是對象,我們遞歸調用深拷貝函數不就好了~
var deepCopy = function(obj) { if (typeof obj !== "object") return; var newObj = obj instanceof Array ? [] : {}; for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] === "object" ? deepCopy(obj[key]) : obj[key]; } } return newObj; }性能問題
盡管使用深拷貝會完全的克隆一個新對象,不會產生副作用,但是深拷貝因為使用遞歸,性能會不如淺拷貝,在開發中,還是要根據實際情況進行選擇。
下期預告難道到這里就結束了?是的。然而本篇實際上是一個鋪墊,我們真正要看的是 jquery 的 extend 函數的實現,下一篇,我們會講一講如何從零實現一個 jquery 的 extend 函數。
專題系列JavaScript專題系列目錄地址:https://github.com/mqyqingfeng/Blog。
JavaScript專題系列預計寫二十篇左右,主要研究日常開發中一些功能點的實現,比如防抖、節流、去重、類型判斷、拷貝、最值、扁平、柯里、遞歸、亂序、排序等,特點是研(chao)究(xi) underscore 和 jQuery 的實現方式。
如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。如果喜歡或者有所啟發,歡迎 star,對作者也是一種鼓勵。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87105.html
摘要:專題系列共計篇,主要研究日常開發中一些功能點的實現,比如防抖節流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究專題之函數組合專題系列第十六篇,講解函數組合,并且使用柯里化和函數組合實現模式需求我們需要寫一個函數,輸入,返回。 JavaScript 專題之從零實現 jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實現一個 jQuery 的 ext...
摘要:寫在前面專題系列是我寫的第二個系列,第一個系列是深入系列。專題系列自月日發布第一篇文章,到月日發布最后一篇,感謝各位朋友的收藏點贊,鼓勵指正。 寫在前面 JavaScript 專題系列是我寫的第二個系列,第一個系列是 JavaScript 深入系列。 JavaScript 專題系列共計 20 篇,主要研究日常開發中一些功能點的實現,比如防抖、節流、去重、類型判斷、拷貝、最值、扁平、柯里...
摘要:為何寫最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。深拷貝如果給放到新的內存中,將的各個屬性都復制到新內存里,就是深拷貝。安全的值是指能夠呈現為有效格式的值。參考文檔冴羽的專題之深淺拷貝深拷貝與淺拷貝的實現 為何寫: 最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。廢話不多說,我們來一起復習一下吧,也希望留下您寶貴意見。 何為深淺拷貝?...
摘要:基本數據類型的復制很簡單,就是賦值操作,所以深淺拷貝也是針對,這類引用類型數據。它會拋棄對象的。另外,查資料過程中還看到這么一個詞結構化克隆算法還有這一篇資料也有參考,也寫得比較詳細了的深淺拷貝 基本數據類型的復制很簡單,就是賦值操作,所以深淺拷貝也是針對Object,Array這類引用類型數據。 淺拷貝對于字符串來說,是值的復制,而對于對象來說則是對對象地址的復制;而深拷貝的話,它不...
閱讀 1952·2021-09-30 09:46
閱讀 1365·2019-08-30 15:43
閱讀 1122·2019-08-29 13:28
閱讀 1922·2019-08-29 11:24
閱讀 1681·2019-08-26 13:22
閱讀 3892·2019-08-26 12:01
閱讀 1816·2019-08-26 11:33
閱讀 3242·2019-08-23 15:34