導語 平常工做開發中,賦值、拷貝是天天都在作的事情,但是有一些拷貝的改變會同時改變原有元素的內容,本次分享主要從拷貝前和拷貝後的數據對比來進行交流探討~數組
如上,一個簡單的賦值和修改,引發了原有元素內容的改變。這種狀況是否也會在你的項目中出現?若是沒出現的,我來分享下,避免後續再有此狀況發生。下面就 針對在什麼狀況下賦值會改變原有對象的值進行進一步說明。首先帶你瞭解下數據類型和基礎概念。微信
JS數據類型分爲:基本數據類型和對象數據類型。markdown
基本數據類型:直接存儲在棧(stack)中的數據。(如String,Number,Boolean,BigInt,undefined,Symbol等)ui
對象數據類型:存儲的是該對象在堆中引用,真實的數據存放在堆內存裏。(主要是包括數組對象和object對象) 以下圖所示:spa
概念:只複製指向某個對象的指針,而不復制對象自己,新舊對象仍是共享同一塊內存prototype
概念:會另外創造一個如出一轍的對象,新對象跟原對象不共享內存指針
賦值賦的實際上是該對象的在棧中的地址,而不是堆中的數據。也就是兩個對象指向的是同一個存儲空間,不管哪一個對象發生改變,其實都是改變的存儲空間的內容,所以,兩個對象是聯動的。code
以上了解了數據類型的存儲和拷貝的基礎概念,來具體看一下哪一些狀況,賦值、拷貝是能夠徹底獨立存在的,哪一些狀況是會改變到原有對象的內容的。請看:按照淺拷貝的基礎概念,寫了一個shallowCopy的方法,而且拷貝後一樣改變原數據中的元素,以下:orm
所獲得的結果是:視頻
總結:name是基礎數據類型,status所在的是對象數據類型,淺拷貝的概念是隻按位拷貝一層,因此基礎數據類型是直接獲得的真實數據,而對象數據類型獲得的是其真實數據的地址引用,因此myinfo和bindinfo中的param所指向的存儲空間是同一個。
Object.assign()
Array.prototype.concat()
Array.prototype.slice()
複製代碼
舉例:
按照深拷貝的基礎概念,一樣寫了一個deepCopy的方法,而且拷貝後一樣改變原數據中的元素,以下:
所獲得的結果是:
總結:name是基礎數據類型,天然不用說,status是對象數據類型,因爲深拷貝是層層遞進拷貝,並不僅是一層,因此拷貝後的新對象和原對象是徹底獨立的,不管哪一個改變,也不會改變另一個對象的內容。因此深拷貝以後,改變新對象的status並未改變原有對象的值。
JSON.parse(JSON.stringify())
Lodash庫中的_.cloneDeep
$.extend
複製代碼
舉例
js老是會有一些特殊狀況,因此開發時要更加謹慎,深拷貝也並非能拷貝全部的類型,例以下面的symbol,由於它是特殊的!
總結:經過上面的例子能夠看到,symbol是一種特殊的數據類型,它的深拷貝也是淺拷貝,因此要格外當心~
同原數據比 | 是否同一對象 | 基本數據類型 | 對象數據類型 |
---|---|---|---|
賦值 | 是 | 會 | 會 |
淺拷貝 | 否 | 不會 | 會 |
深拷貝 | 否 | 不會 | 不會 |
賦值:兩個指向同一個對象,不管哪一個改變,另一個都會跟着改變。
淺拷貝:雖然不是同一對象,可是若是原數據都是基礎數據類型,淺拷貝就是深拷貝,各自獨立,不然若是有對象數據類型,就會出現聯動現象。
深拷貝:不是同一對象,原數據和新數據是相互獨立,互不影響的,但要注意symbol類型
原做者: 任春豔
未經贊成,禁止轉載!
更多精彩內容,盡請關注騰訊VTeam技術團隊微信公衆號和視頻號