摘要:兩者享有相同的引用。深拷貝這個問題通常可以通過來解決。深淺拷貝也可以使用的方法,注意使用合并返回值
前言
最近寫代碼經(jīng)常用到深淺拷貝,從一開始的悶頭使用漸漸想要深究其理,這篇文章記錄一下我的認為,有所不足,恭請指正
我們可以先看看一個常遇到的一個小問題
let a = { age:1 } let b = a a.age = 2 console.log(b.age) //2
從上面的例子中我們看到了,如果給一個變量賦值一個對象,那么兩者的值會是同一個引用,其中一方變化,另一方也會有相應(yīng)的改變。
通常我們開發(fā)中不希望出現(xiàn)這樣的問題,我們可以使用淺拷貝來解決這個問題。
首先可以通過 Object.assign 來解決這個問題。
let a = { age:1 } let b = Object.assign({} , a) a.age = 2 console.log(b.age) //1
當(dāng)然大多數(shù)情況我們比較喜歡通過展開運算符(...)來解決
let a = { age:1 } let b ={...a} a.age = 2 console.log(b.age) //1
通常淺拷貝就解決了大部分問題,但是如果遇到以下情況就需要用到深拷貝了
let a = { age:1, jobs:{ first:"FE" } } let b ={...a} a.jobs.first = "native" console.log(b.jobs.first) //native
淺拷貝只解決了第一層的問題,如果接下去的值還是有對象的話,那么就又回到剛剛的開始問題了。兩者享有相同的引用。要解決這個問題,我們就要引入深拷貝。
深拷貝這個問題通??梢酝ㄟ^ JSON.parse(JSON.stringify(object)) 來解決。
let a = { age:1, jobs:{ first:"FE" } } let b =JSON.parse(JSON.stringify(a)) a.jobs.first = "native" console.log(b.jobs.first) //FE
但是該方法也是有局限性的:
會忽略underfind
不能序列化函數(shù)
不能解決循環(huán)引起的對象
我們再看一下下面這個情況
let obj ={ a:undefined, b:function(){}, name:"yck" } let newObj = JSON.parse(JSON.stringify(obj)) console.log(newObj) //{name : "yck"}
你會發(fā)現(xiàn)在上述情況中,該方法忽略掉函數(shù)和undefind
但是在通常情況下,復(fù)雜數(shù)據(jù)都是可序列化的,所以這個函數(shù)可以解決大部分問題,并且該函數(shù)是內(nèi)置函數(shù)中處理深拷貝性能最快的。當(dāng)然如果你的數(shù)據(jù)中含有以上三種情況下??梢允褂?lodash 的深拷貝函數(shù)
如果你所需要拷貝的對含有內(nèi)置類型并且不包括函數(shù),可以使用 MessageChannel
function structuralClone(obj){ return new Promise(resolve => { const {port1,port2} = new MessageChannel(); port2.onmessage = ev =>resolve(ev.data); port1.postMessage(obj) }) } var obj = {a:1,b:{ c:b }} //注意這個方法是異步的 //可以處理undefined和循環(huán)引用對象 const clone = await structuralClone(obj);深拷貝與淺拷貝的區(qū)別
深拷貝和淺拷貝最根本的區(qū)別在于是否是真正獲取了一個對象的復(fù)制實體,而不是引用。
淺拷貝—-只是拷貝了基本類型的數(shù)據(jù),而引用類型數(shù)據(jù),拷貝后也是會發(fā)生引用,我們把這種拷貝叫做“(淺復(fù)制)淺拷貝”,換句話說,淺拷貝僅僅是指向被拷貝的內(nèi)存地址,如果原地址中對象被改變了,那么淺拷貝出來的對象也會相應(yīng)改變。
深拷貝—-在計算機中開辟了一塊新的內(nèi)存地址用于存放復(fù)制的對象。
淺拷貝實例
//此遞歸方法不包含數(shù)組對象
var obj = { a:1, arr: [2,3] }; var shallowObj = shallowCopy(obj); function shallowCopy(src) { var newobj = {}; for (var prop in src) { if (src.hasOwnProperty(prop)) { newobj[prop] = src[prop]; } } return newobj;
因為淺復(fù)制只會將對象的各個屬性進行依次復(fù)制,并不會進行遞歸復(fù)制,而 JavaScript 存儲對象都是存地址的,所以淺復(fù)制會導(dǎo)致 obj.arr 和 shallowObj.arr 指向同一塊內(nèi)存地址,大概的示意圖如下。
導(dǎo)致的結(jié)果就是:
shallowObj.arr[1] = 5; console.log(obj.arr[1]); // 5
深拷貝實例
而深復(fù)制則不同,它不僅將原對象的各個屬性逐個復(fù)制出去,而且將原對象各個屬性所包含的對象也依次采用深復(fù)制的方法遞歸復(fù)制到新對象上。這就不會存在上面 obj 和 shallowObj 的 arr 屬性指向同一個對象的問題。
var obj = { a:1, arr: [1,2], nation : "中國", birthplaces:["北京","上海","廣州"] }; var obj2 = {name:"楊"}; obj2 = deepCopy(obj,obj2); console.log(obj2); //深復(fù)制,要想達到深復(fù)制就需要用遞歸 function deepCopy(o,c){ var c = c || {}; for(var i in o){ if(typeof o[i] === "object"){ //要考慮深復(fù)制問題了 if(o[i].constructor === Array){ //這是數(shù)組 c[i] =[]; }else{ //這是對象 c[i] = {}; } deepCopy(o[i],c[i]); }else{ c[i] = o[i]; } } return c }
結(jié)果如下面的示意圖所示:
這樣obj和obj2分別擁有不同的內(nèi)存地址,兩邊值的改變互不影響。
深淺拷貝也可以使用JQuery的extend方法,注意使用合并返回值
let newObj = $.extend(true,{},partcontent);
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/96765.html
摘要:為何寫最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。深拷貝如果給放到新的內(nèi)存中,將的各個屬性都復(fù)制到新內(nèi)存里,就是深拷貝。安全的值是指能夠呈現(xiàn)為有效格式的值。參考文檔冴羽的專題之深淺拷貝深拷貝與淺拷貝的實現(xiàn) 為何寫: 最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。廢話不多說,我們來一起復(fù)習(xí)一下吧,也希望留下您寶貴意見。 何為深淺拷貝?...
摘要:前言里面淺拷貝和深拷貝是非常關(guān)鍵的知識點,今天就來通過本文清楚的了解深淺拷貝以及該如何實現(xiàn)這兩種拷貝方式。對象的拷貝又分為淺拷貝和深拷貝。印證了上述所說的對于所有的基本類型,簡單的賦值已經(jīng)是實現(xiàn)了深拷貝。 前言 JavaScript里面淺拷貝和深拷貝是非常關(guān)鍵的知識點,今天就來通過本文清楚的了解深淺拷貝以及該如何實現(xiàn)這兩種拷貝方式。 深淺拷貝的區(qū)別 拷貝:其實就是一個對象復(fù)制給另外...
摘要:在之前的文章專題之?dāng)?shù)據(jù)類型和類型檢測中我有講過,中的數(shù)據(jù)類型分為兩種,基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,基本數(shù)據(jù)類型是保存在棧的數(shù)據(jù)結(jié)構(gòu)中的是按值訪問,所以不存在深淺拷貝問題。 前言 在開發(fā)過程中,偶爾會遇到這種場景,拿到一個數(shù)據(jù)后,你打算對它進行處理,但是你又希望拷貝一份副本出來,方便數(shù)據(jù)對比和以后恢復(fù)數(shù)據(jù)。 那么這就涉及到了 JS 中對數(shù)據(jù)的深淺拷貝問題,所謂深淺拷貝,淺拷貝的意思就是,...
摘要:面試的心得體會簡歷制作我做了兩份簡歷,用兩個手機賬號,兩個簡歷名字,分別在各個招聘網(wǎng)站投了雙份簡歷,一個是數(shù)據(jù)分析的簡歷一個是全棧開發(fā)的簡歷,我真正接觸快年,不管是學(xué)習(xí)還是工作學(xué)到的東西,這兩年大概掌握了前端爬蟲數(shù)據(jù)分析機器學(xué)習(xí)技術(shù), showImg(https://upload-images.jianshu.io/upload_images/13090773-b96aac7e974c...
閱讀 2913·2021-11-24 09:39
閱讀 1723·2021-09-28 09:35
閱讀 1178·2021-09-06 15:02
閱讀 1446·2021-07-25 21:37
閱讀 2833·2019-08-30 15:53
閱讀 3710·2019-08-30 14:07
閱讀 767·2019-08-30 11:07
閱讀 3604·2019-08-29 18:36