文章首次發表於 我的博客,系列文章目錄:github.com/funnycoders…前端
基本類型數據保存在在棧內存中 引用類型數據保存在堆內存中,引用數據類型的變量是一個指向堆內存中實際對象的引用,存在棧中。git
爲何基本數據類型存在棧內存,引用數據類型存在堆內存?github
基本類型賦值,系統會爲新的變量在棧內存中分配一個新值,這個很好理解。 引用類型賦值,系統會爲新的變量在棧內存中分配一個值,這個值僅僅是指向同一個對象的引用,和原對象指向的都是堆內存中的同一個對象。面試
var obj1 = new Object();
var obj2 = obj1;
obj1.name = 'lucyStar';
console.log(obj2.name);
// lucyStar
複製代碼
咱們能夠看到,obj1保存了一個對象的實例,這個值被賦值到 Obj2中。賦值操做完成後,兩個變量實際引用的是同一個對象,改變了其中一個,會影響另一個值。數組
什麼是淺拷貝? 若是是對象類型,則只拷貝一層,若是對象的屬性又是一個對象,那麼此時拷貝的就是此屬性的引用。微信
簡單實現一個淺拷貝markdown
function shadowCopy(obj) {
const newObj = {};
for(let prop in obj) {
if(obj.hasOwnProperty(prop)){
newObj[prop] = obj[prop];
}
}
return newObj;
}
const obj1 = {
name: 'litterStar',
a: {
b: '1'
}
};
const obj2 = shadowCopy(obj1);
obj2.name = 'lucyStar';
obj2.a.b = '2';
console.log(obj1);
// { name: 'litterStar', a: { b: '2' } }
console.log(obj2);
// { name: 'lucyStar', a: { b: '2' } }
複製代碼
能夠看到修改obj2
的name
屬性不會影響 obj1
,可是修改 obj2
的 a屬性(是個對象)的 b,就會影響 obj1.a.b函數
使用下面這些函數獲得的都是淺拷貝:post
Object.assign
Array.prototype.slice()
, Array.prototype.concat()
什麼是深拷貝? 淺拷貝是隻拷貝一層,深拷貝會拷貝全部的屬性。深拷貝先後兩個對象互不影響。學習
深拷貝的實現
JSON.parse(JSON.stringify())
JSON.parse(JSON.stringify())
有存在如下問題:
嘗試本身寫一個深拷貝,須要考慮下面這幾種狀況
obj.prop1 = obj
function deepCopy(originObj, map = new WeakMap()) {
// 判斷是否爲基本數據類型
if(typeof originObj === 'object') {
// 判斷是都否爲數組
const cloneObj = Array.isArray(originObj) ? [] : {};
// 判斷是否爲循環引用
if(map.get(originObj)) {
return map.get(originObj);
}
map.set(originObj, cloneObj);
for(const prop in originObj) {
cloneObj[prop] = deepCopy(originObj[prop], map);
}
return cloneObj;
} else {
return originObj;
}
}
const obj1 = {
a: '111',
}
obj1.obj2 = obj1;
const aa = deepCopy(obj1);
console.log(aa);
// { a: '111', obj2: [Circular] }
複製代碼
上面只是實現一個簡單的深拷貝,不少狀況未考慮到,好比 特殊的數據類型及兼容性的處理,更多細節的實現能夠參考 lodash 中的 cloneDeep方法。
和原數據是否指向同一對象 | 第一層數據爲基本數據類型 | 原數據中包含對象 | |
---|---|---|---|
賦值 | 是 | 改變會使原數據一同改變 | 改變會使原數據一同改變 |
淺拷貝 | 否 | 改變不會使原數據一同改變 | 改變會使原數據一同改變 |
深拷貝 | 否 | 改變不會使原數據一同改變 | 改變不會使原數據一同改變 |
備註:markdown 表格在 tableconvert.com/ 該網站生成,很方便。
最近發起了一個100天前端進階計劃,主要是深挖每一個知識點背後的原理,歡迎關注 微信公衆號「牧碼的星星」,咱們一塊兒學習,打卡100天。