堆內存和棧內存
一、在js中,變量的儲存對象主要有倆種方式:堆內存和棧內存;
二、 js中 數據類型有 值類型(基本數據類型){String number boolean null(null雖然作爲一個object類型,但也是基本數據類型) undefined symbol}和引用數據類型{object array function}
三、 棧內存主要存儲的是值類型(基本數據類型)以及堆內存中對象變量的指針;
四、堆內存主要存儲引用數據類型;
五、棧內存是有序存儲,容量小,系統分配率高;堆內存首先要分配存儲區域,之後再把這個區域的位置(指針)存儲到棧內存中;這就是爲啥js在訪問對象時,得根據地址(指針)去獲取對象得值;
深拷貝和淺拷貝都是圍繞堆內存和棧內存展開的,一個是處理堆內存中得值,一個是處理棧內存中的指針;
六、在棧內存中,基本數據類型都是相互獨立的,互不影響;而在堆內存中,一個引用類型可以有多個指針,這些指針都指向同一個堆內存中的對象;某一個指針對這個引用類型的修改,其他指針指向的是被修改後的引用類型;
淺拷貝和深拷貝都是針對引用數據類型
七、淺拷貝只是複製指針,不復制引用數據類型本身;
八、深拷貝會複製引用數據類型本身,倆個對象一摸一樣;新舊對象互不影響;
寫一個淺拷貝方法
function lightcopy (zrobj) {
var obj = {};
//拷貝一層,深層次的對象就拷貝引用
for(var i in zrobj){
obj[i] = zrobj[i]
}
return obj;
}
var obj = {
a:'1',
b:{
a:'2',
fn(){
console.log(this.a)
}
}
}
var nowCopyObjOne = lightcopy(obj);
var nowCopyObjTwo = lightcopy(obj);
console.log(nowCopyObjOne.a) //1
console.log(nowCopyObjOne.b.a) //2
console.log(nowCopyObjOne.b.fn()) //2
console.log(nowCopyObjTwo.a) //1
console.log(nowCopyObjTwo.b.a) //2
console.log(nowCopyObjTwo.b.fn()) //2
nowCopyObjOne.b.a = '我被nowCopyObjOne修改啦'
console.log(nowCopyObjOne.a) //1
console.log(nowCopyObjOne.b.a) //我被nowCopyObjOne修改啦
console.log(nowCopyObjOne.b.fn()) //我被nowCopyObjOne修改啦
console.log(nowCopyObjTwo.a) //1
console.log(nowCopyObjTwo.b.a) //我被nowCopyObjOne修改啦
console.log(nowCopyObjTwo.b.fn()) //我被nowCopyObjOne修改啦
用ES6裏面的Object.assign()《本身是用來合併多個對象》實現一個淺拷貝
Object.assign(target, …sources) target爲目標對象。sources爲任意多個源對象。
var a = {
name:'睿睿'
};
var b = {
age:'18'
};
var c = {
gender:'男'
};
var d = {
position:'程序猿'
};
Object.assign(b,c,d);
console.log(b)//{age: "18", gender: "男", position: "程序猿"}
//該方法會修改傳入的第一個對象;所以要實現淺拷貝的話 第一個參數傳{};
var dCopy = Object.assign({} , a , b , c , d)
//如果有重複的屬性,會被右邊的值覆蓋,按照參數從左到右的順序
//此時,由於Object.assign(b,c,d); 所以 b已經成爲{age: "18", gender: "男", position: "程序猿"}
//所以:c 和 d 裏面的屬性會覆蓋b中的屬性
console.log(dCopy)//{name: "睿睿", age: "18", gender: "男", position: "程序猿"}
寫一個深拷貝的方法(遞歸)
function deepClone(obj) {
var deepObj = {};
for(var key in obj) {
//判斷對象是否有下一級
if (Object.prototype.hasOwnProperty.call(obj, key)) {
//如果下一級也是對象
if (typeof obj[key] === 'object') {
//遞歸
deepObj[key] = deepClone(obj[key]);
} else {
deepObj[key] = obj[key];
}
}
}
return deepObj;
}
var obj = {
a:'1',
b:{
a:'2',
fn(){
console.log(this.a)
}
}
}
var deepCopyobjOne = deepClone(obj)
var deepCopyobjTwo = deepClone(obj)
console.log(deepCopyobjOne.a) //1
console.log(deepCopyobjTwo.a) //1
deepCopyobjOne.a='3';
console.log(deepCopyobjOne.a) //3
console.log(deepCopyobjTwo.a) //1
用JSON.parse和JSON.stringify實現深拷貝
var obj = {
a:'1',
b:{
a:'2',
fn(){
console.log(this.a)
}
}
}
var deepObjJSONOne = JSON.parse(JSON.stringify(obj));
var deepObjJSONTwo = JSON.parse(JSON.stringify(obj));
console.log(deepObjJSONOne.a) //1
console.log(deepObjJSONTwo.a) //1
deepObjJSONOne.a='3';
console.log(deepObjJSONOne.a) //3
console.log(deepObjJSONTwo.a) //1
完!
(方法很實用,懂的比較淺,有問題多多指出;謝謝)