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