浅浅理解一下深克隆和浅克隆
一、深克隆:基本數據類型的賦值
????????進行深克隆的是八大基本數據類型(byte,short,int,long,float,double,char,boolean)
????????大白話理解一下:就是指將數據拷貝后兩者無關聯,改變一個不會影響到另一個數值變化。
接下來我們來看看為什么會這樣:首先,基礎數據類型的存儲是直接存儲在棧內存中的。如此時有一個變量a,當進行賦值操作b=a時,在棧中會為變量開辟一個新的內存空間來存儲b 所以a和b位于兩個完全不同的存儲空間,只是值相同而已,改變a自然b不會發生變化
深拷貝舉例
let a=1;let b=a;a=3;console.log(a)//3console.log(b)//1二、淺克隆:引用數據類型的賦值
????????進行淺克隆的一般是數組和對象
????????繼續大白話一下:淺克隆就是數據拷貝后,一方數據變化另一方會跟著變化。
引用數據類型只是把地址存在了棧內存中,真正的數據內容是存放在堆內存中的。而這類數據進行賦值時,復制過去的只是地址(相當于其他語言中的引用)。可以這樣想:當我賦值? 時,我只是給了你我家的門牌號,所以我們屋子里的東西是相同的,如果我拿走了一樣物品,你的屋子里也會缺少這件物品(當然了,我們住在一所房子里)。當我們用obj給obj2賦值時,復制過去的只是obj的地址,所以obj改變后,obj2也跟著改變了。
對象淺拷貝舉例
let obj={name: 'zs',age: 18,from: 'china', }let obj2=obj;obj.name="lisi"console.log(obj)//{name: 'lisi', age: 18, from: 'china'}console.log(obj2)//{name: 'lisi', age: 18, from: 'china'}三、實現引用數據類型的深拷貝
????????那么現在問題來了,假如我有一個數組或是對象,我就是想要復制一份并讓他和原數組/對象毫無關系,應該怎樣做呢?我們希望在地址復制過去的同時,在堆內存上為新數據開辟一塊空間。
????????不如先來想想怎么讓引用數據類型變成基本數據類型。啊!原來有一個JSON方法實現對象、數組和字符串之間的轉換! 我們先將obj變成字符串,再進行字符串的賦值(基本數據類型的賦值,深拷貝),最后再將復制好的字符串變回對象和數組不就成了嗎!????
????????在這里小小插入一下JSON的有關內容:
????????JSON 通常用于與服務端交換數據。在接收服務器數據時一般是字符串。因此,一個常用的方法用來將數據轉換成字符串:我們一般只使用他的第一個參數:需要被轉換成字符串的數據內容value(通常為對象或數組),對剩下兩個參數感興趣的小伙伴可以自行查閱文檔
JSON.stringify(value[, replacer[, space]])????????另一個常用的方法是將字符串轉換成對象,同樣,我們只使用他的第一個參數text傳一個合法字符串
JSON.parse(text[, reviver])??????? 接下來我們就可以實現對象的深克隆了:還是上面的張三,只不過這次obj中的name變成李四之后,obj2沒有跟著改變了。
let obj={name: 'zs',age: 18,from: 'china', }let tem=JSON.stringify(obj)let obj2=tem;obj2=JSON.parse(obj2)obj.name="lisi"console.log(obj)//{name: 'lisi', age: 18, from: 'china'}console.log(obj2)//{name: 'zs', age: 18, from: 'china'}????????那數組又該怎樣操作呢,如果對象中不只是基本數據類型,又該怎樣操作呢?通過上面的例子我們可以知道,對象中可能都是基本數據類型,他們以鍵值對的方式存在,而基本數據類型的復制是深拷貝。當我們想將一個引用數據類型進行深拷貝,只需要把里面所有的值都復制一遍就行了!
????????接下來我們封裝一個實現數據深克隆的函數deepClone:
var obj1 = {a: 1,b: {like: 'eat'},arr: ['ad', 11,[1,2,3]]}const deepClone = (obj) => {if (typeof (obj) == "object") {let res;console.log("引用數據類型")if (Array.isArray(obj)) {res = [];console.log("數組")for (val of obj) {res.push(deepClone( val ))}} else {res = {};console.log("對象")for (item in obj) {res[item]= deepClone(obj[item])}}return res} else {console.log("基本數據類型")return obj}}var obj2 = deepClone(obj1);obj1.b.like = "drank"obj1.a="hello"obj1.arr[2][1]="world"console.log(obj1)console.log(obj2)??????? 最后輸出的結果如圖,讓我們來分析一下這個函數是如何執行的:我們創建一個空遍歷res用來存儲最后的結果。首先obj是一個對象,循環遍歷對象中的三個元素,第一個是基本數據類型,將其值obj[item]也就是1遞歸調用函數作為參數,因為他是基本數據類型,所以直接返回了。第二個元素同樣遞歸后因為是對象,再遞歸一次變成基本數據類型返回。第三元素...n次遞歸之后,所有元素都成功在變成基本數據類型之后被復制了。左下輸出很清晰的展現了函數的執行過程。
?
?
?
總結
以上是生活随笔為你收集整理的浅浅理解一下深克隆和浅克隆的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公司注册资金到底多少才是最好
- 下一篇: vue 一键修复eslint问题(web