我們知道js中那些是值類型,那些是引用類型介褥,這是必須要搞清楚座掘。
JavaScript中的值類型:數值递惋、布爾值、null溢陪、undefined
JavaScript中的引用類型:對象萍虽、數組、函數
堆棧
棧(stack)
由操作系統(tǒng)自動分配釋放 形真,存放函數的參數值杉编,局部變量的值等。其操作方式類似于數據結構中的棧咆霜。一種先進后出的數據結構邓馒。堆(heap)
動態(tài)分配的內存,大小不定也不會自動釋放蛾坯。隊列優(yōu)先,先進先出光酣。
值類型是存放在棧中的基本類型,對象數據則是在堆中創(chuàng)建并在棧中保留對象在堆中的地址脉课。我們從下面的例子來理解
var a = [1,2,3,4,5];
var b = a;
var c = a[0];
數據在內存中的存儲示意圖(圖片來自‘小輝_Ray’的博客)
通過變量在內存中的存儲我們可以看出來救军,所有的變量都是在棧內存中存在的,不同的是值類型存放的是值本身倘零,引用類型存放的是指向堆內存對象的地址唱遭。
基本類型與引用類型最大的區(qū)別實際就是傳值與傳址的區(qū)別。
var a =1;
var array = [1,2,3];
var object = {a:1,b:2,c:3};
function reassign(num,arr,obj){
//將參數重新賦值
num = '';
//arr 是array對象的引用拷貝呈驶,我們把這個引用重新賦值拷泽,這時的arr不在指向array所指向的對象,而是指向新的空數組
//所以這時候我們再對arr進行操作袖瞻,將不會影響array司致。
//obj同理
arr = [];
arr.push(123);
obj = '';
}
function operate(num,arr,obj){
num = 2;
arr.push(4);
obj.test = 'test';
// 我們直接對傳遞的參數進行操作,
// 參數num是值類型聋迎,傳遞的是參數a的值拷貝蚌吸,所以我們對num進行操作不會影響外層的a變量
// arr,和obj,一個是數組砌庄,一個是對象,都是引用類型奕枢,傳遞的是對象地址的拷貝娄昆,我們對它的操作也會影響到外層變量的值,因為他們都指向相同的堆對象缝彬。
}
reassign(a,array,object);
console.log(a); // 1
console.log(array); // [1,2,3]
console.log(object); // {a:1,b:2,c:3}
operate(a,array,object);
console.log(a); // 1
console.log(array); // [1,2,3,4]
console.log(object); // {a:1,b:2,c:3,test:'test'}
對象的拷貝
js 深拷貝 vs 淺拷貝
淺拷貝
//如果對象的屬性是引用類型萌焰,對對象的屬性進行拷貝時,拷貝的只是對象屬性的引用
function Copy(object) {
var temp = {};
for (var property in object) {
temp[property] = object[property];
}
return temp;
}
var obj = {}
obj.a = "abc";
obj.b = [1,2];
var copyObj = Copy(obj);
console.log(copyObj); // { a: 'abc', b: [ 1,2] }
copyObj.b.push(3); //這里向copyObj的b屬性中push一個值谷浅,原始的obj對象也會受到影響扒俯,因為數組是引用類型
console.log(obj); //{ a: 'abc', b: [ 1, 2, 3 ]}
深拷貝
// 實際編碼中奶卓,很多時候淺拷貝并是我們想要的,我們希望拷貝完成后的對象和原對象不再有任何關聯(lián)撼玄。
// 深拷貝
function Copy(source, target) {
var target = target || {};
for (var i in source) {
if (typeof source[i] === 'object') { //這里有個疑問夺姑, 如果對象的屬性是函數呢?
target[i] = (source[i].constructor === Array) ? [] : {};
Copy(source[i], target[i]);
} else {
target[i] = source[i];
}
}
return target;
}
var obj = {}
obj.a = "abc";
obj.b = [1,2];
obj.c = function(){};
var copyObj = Copy(obj);
copyObj.b.push(3); //這里向copyObj的b屬性中push一個值掌猛,原始的obj對象也會受到影響盏浙,因為數組是引用類型
console.log(copyObj); // { a: 'abc', b: [ 1,2] }
console.log(obj); //{ a: 'abc', b: [ 1, 2, 3 ]}