摘要:基本數(shù)據(jù)類(lèi)型的復(fù)制很簡(jiǎn)單,就是賦值操作,所以深淺拷貝也是針對(duì),這類(lèi)引用類(lèi)型數(shù)據(jù)。它會(huì)拋棄對(duì)象的。另外,查資料過(guò)程中還看到這么一個(gè)詞結(jié)構(gòu)化克隆算法還有這一篇資料也有參考,也寫(xiě)得比較詳細(xì)了的深淺拷貝
基本數(shù)據(jù)類(lèi)型的復(fù)制很簡(jiǎn)單,就是賦值操作,所以深淺拷貝也是針對(duì)Object,Array這類(lèi)引用類(lèi)型數(shù)據(jù)。
淺拷貝對(duì)于字符串來(lái)說(shuō),是值的復(fù)制,而對(duì)于對(duì)象來(lái)說(shuō)則是對(duì)對(duì)象地址的復(fù)制;實(shí)現(xiàn)方式 原生JS實(shí)現(xiàn):而深拷貝的話,它不僅將對(duì)象的各個(gè)屬性逐個(gè)復(fù)制出來(lái),還將各個(gè)屬性所包含的對(duì)象也依次復(fù)制出來(lái),相當(dāng)于在堆區(qū)又新開(kāi)了一塊地存放,主要采取遞歸來(lái)實(shí)現(xiàn)。
淺拷貝:
let originObj={ color:["red","green"], num:5 }; function shallowClone(obj){ let newObj=(obj instanceof Array) ? []:{}; for(let item in obj){ if(obj.hasOwnProperty(item)){ // 避免列舉出原型上的屬性 newObj[item]=obj[item]; } } return newObj; } let cloneObj=shallowClone(originObj);
深拷貝:
function deepClone(obj){ let newObj=(obj instanceof Array)? [] : {}; for(let item in obj){ if(obj.hasOwnProperty){ const val=obj[item]; debugger newObj[item]=typeof val==="object" ? deepClone(val) : val; } } return newObj; } let cloneObj2=deepClone(originObj);
其實(shí),這種深拷貝的實(shí)現(xiàn)還是有些問(wèn)題的,比如日期,正則對(duì)象無(wú)法復(fù)制,還有一個(gè)是循環(huán)引用,類(lèi)似閉包會(huì)內(nèi)存泄露一樣,這樣的對(duì)象深拷貝也會(huì)陷入一個(gè)閉環(huán),直到棧溢出。
為了解決這個(gè)問(wèn)題,就得先判斷這個(gè)對(duì)象是否等于原對(duì)象。
function deepClone(obj){ let tempArr=[]; let newObj=(obj instanceof Array) ? [] : {}; tempArr.push(obj); for(let item in obj){ if(typeof obj[item] === "object"){ const index=tempArr.indexOf(obj[item]); // 如果已存在,證明引用了相同對(duì)象,那么無(wú)論是循環(huán)引用還是重復(fù)引用,我們返回引用就可以了 if(index>-1){ newObj[item]=tempArr[index]; }else{ newObj[item]=obj[item]; } }else{ newObj[item]=obj[item]; } } return newObj; }ES6實(shí)現(xiàn)
let newObj1=Object.assgin({},originObj); let newObj2={...obj}; // 數(shù)組用[...obj]
注:Object.assgin和擴(kuò)展運(yùn)算符實(shí)現(xiàn)的都是淺拷貝。JSON實(shí)現(xiàn):
這種方法簡(jiǎn)單是簡(jiǎn)單,不過(guò)這個(gè)方法有以下缺陷:
1.會(huì)忽略函數(shù)對(duì)象以及原型對(duì)象,正則會(huì)復(fù)制成空對(duì)象,而日期對(duì)象會(huì)變成字符串。 2.它會(huì)拋棄對(duì)象的constructor。也就是深拷貝之后,不管這個(gè)對(duì)象原來(lái)的構(gòu)造函數(shù)是什么,在深拷貝之后都會(huì)變成Object; 3.如果對(duì)象中存在循環(huán)引用的情況無(wú)法正確處理。
按需取用吧。
let originObj={fn:function(){console.log(111)}, colors:["red","gree"],reg:/s/g}; let newObj=JSON.parse(JSON.stringify(originObj));第三方庫(kù)實(shí)現(xiàn):
轉(zhuǎn)自鏈接:深入剖析 JavaScript 的深復(fù)制
Underscore —— _.clone()順便安利下underscore,真的挺好用的一個(gè)庫(kù): Underscore中文文檔
這個(gè)方法實(shí)際上是一種淺復(fù)制 (shallow-copy),所有嵌套的對(duì)象和數(shù)組都是直接復(fù)制引用而并沒(méi)有進(jìn)行深復(fù)制。
let originObj={ color:["red","green"], num:5 }; let newObj=_.clone(originObj); newObj.colors.push("grey"); originObj.colors; // ["red","green","grey"];
源碼邏輯很簡(jiǎn)單:(當(dāng)然調(diào)用的其他方法也是underscore的)
// Create a (shallow-cloned) duplicate of an object. _.clone = function(obj) { if (!_.isObject(obj)) return obj; return _.isArray(obj) ? obj.slice() : _.extend({}, obj); }jQuery —— $.extend()
這個(gè)用法很簡(jiǎn)單:
let originObj={ color:["red","green"], num:5 }; let shallowClone=$.extend({},originObj); // 淺拷貝 let deepClone=$.extend(true,{},originObj); // 深拷貝,第一個(gè)參數(shù)表示是否深度合并對(duì)象lodash —— _.clone() / _.cloneDeep()
lodash深拷貝——這個(gè)算是這幾個(gè)里面最完善的方法了,日期,函數(shù),正則對(duì)象通通都能復(fù)制。
在lodash中關(guān)于復(fù)制的方法有兩個(gè),分別是_.clone()和_.cloneDeep()。其中_.clone(obj, true)等價(jià)于_.cloneDeep(obj)。
沒(méi)引入的可以點(diǎn)擊上面的文檔鏈接去直接改動(dòng)代碼試試看。
另外,查資料過(guò)程中還看到這么一個(gè)詞:結(jié)構(gòu)化克隆算法
還有這一篇資料也有參考,也寫(xiě)得比較詳細(xì)了:JS的深淺拷貝
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/99349.html
摘要:為何寫(xiě)最近在研究深淺拷貝,找了很多資料,感覺(jué)不是很滿意,所以自己就整理了一份。深拷貝如果給放到新的內(nèi)存中,將的各個(gè)屬性都復(fù)制到新內(nèi)存里,就是深拷貝。安全的值是指能夠呈現(xiàn)為有效格式的值。參考文檔冴羽的專(zhuān)題之深淺拷貝深拷貝與淺拷貝的實(shí)現(xiàn) 為何寫(xiě): 最近在研究深淺拷貝,找了很多資料,感覺(jué)不是很滿意,所以自己就整理了一份。廢話不多說(shuō),我們來(lái)一起復(fù)習(xí)一下吧,也希望留下您寶貴意見(jiàn)。 何為深淺拷貝?...
摘要:一數(shù)據(jù)類(lèi)型基本類(lèi)型引用類(lèi)型類(lèi)型判斷返回結(jié)果未定義布爾值字符串?dāng)?shù)值對(duì)象或者函數(shù)拓展堆棧兩種數(shù)據(jù)結(jié)構(gòu)堆隊(duì)列優(yōu)先,先進(jìn)先出由操作系統(tǒng)自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。 一、數(shù)據(jù)類(lèi)型 基本類(lèi)型:`Null Boolean String Undefined Number(NB SUN)` 引用類(lèi)型:`Array Function Object` 類(lèi)型判斷:typeof 返回結(jié)果...
摘要:在之前的文章專(zhuān)題之?dāng)?shù)據(jù)類(lèi)型和類(lèi)型檢測(cè)中我有講過(guò),中的數(shù)據(jù)類(lèi)型分為兩種,基本數(shù)據(jù)類(lèi)型和引用數(shù)據(jù)類(lèi)型,基本數(shù)據(jù)類(lèi)型是保存在棧的數(shù)據(jù)結(jié)構(gòu)中的是按值訪問(wèn),所以不存在深淺拷貝問(wèn)題。 前言 在開(kāi)發(fā)過(guò)程中,偶爾會(huì)遇到這種場(chǎng)景,拿到一個(gè)數(shù)據(jù)后,你打算對(duì)它進(jìn)行處理,但是你又希望拷貝一份副本出來(lái),方便數(shù)據(jù)對(duì)比和以后恢復(fù)數(shù)據(jù)。 那么這就涉及到了 JS 中對(duì)數(shù)據(jù)的深淺拷貝問(wèn)題,所謂深淺拷貝,淺拷貝的意思就是,...
摘要:專(zhuān)題系列第六篇,講解深淺拷貝的技巧和以及實(shí)現(xiàn)深淺拷貝的思路前言拷貝也是面試經(jīng)典吶數(shù)組的淺拷貝如果是數(shù)組,我們可以利用數(shù)組的一些方法比如返回一個(gè)新數(shù)組的特性來(lái)實(shí)現(xiàn)拷貝。所以我們可以看出使用和是一種淺拷貝。 JavaScript 專(zhuān)題系列第六篇,講解深淺拷貝的技巧和以及實(shí)現(xiàn)深淺拷貝的思路 前言 拷貝也是面試經(jīng)典吶! 數(shù)組的淺拷貝 如果是數(shù)組,我們可以利用數(shù)組的一些方法比如:slice、co...
摘要:專(zhuān)題系列共計(jì)篇,主要研究日常開(kāi)發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖節(jié)流去重類(lèi)型判斷拷貝最值扁平柯里遞歸亂序排序等,特點(diǎn)是研究專(zhuān)題之函數(shù)組合專(zhuān)題系列第十六篇,講解函數(shù)組合,并且使用柯里化和函數(shù)組合實(shí)現(xiàn)模式需求我們需要寫(xiě)一個(gè)函數(shù),輸入,返回。 JavaScript 專(zhuān)題之從零實(shí)現(xiàn) jQuery 的 extend JavaScritp 專(zhuān)題系列第七篇,講解如何從零實(shí)現(xiàn)一個(gè) jQuery 的 ext...
閱讀 1650·2019-08-30 13:18
閱讀 1634·2019-08-29 12:19
閱讀 2186·2019-08-26 13:57
閱讀 4209·2019-08-26 13:22
閱讀 1262·2019-08-26 10:35
閱讀 3049·2019-08-23 18:09
閱讀 2596·2019-08-23 17:19
閱讀 744·2019-08-23 17:18