js中值的基本型別與引用型別,以及物件引用,物件的淺拷貝與深拷貝
阿新 • • 發佈:2019-01-01
js有兩種型別的值:
棧:原始資料型別(undefinen,null,boolead,number,string)
堆:引用資料型別(物件,函式和陣列)
兩種型別的區別是:儲存位置不同,
原始資料型別直接儲存在棧(stack)中的簡單資料段,佔據空間小,大小固定,屬於被頻繁使用的資料,所以放入棧中儲存;
引用資料型別儲存在堆(heap)中的物件,佔據空間大,大小不固定,如果儲存在棧中,將會影響程式執行的效能,引用資料型別在棧中儲存了指標,該指標指向堆中該屍體的起始地址。當直譯器尋找引用值,會首先檢索其在棧中的地址,取得地址後從堆中獲取實體;
舉個例子:
基本型別:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"var obj={}; var objcopy=obj; objcopy.fun=function(){ console.trace(); console.log('obi.fun'); }; obj.fun();//obi.fun同樣會執行objcopy新增的fun方法,證明倆人是引用的同樣的東東> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>無標題文件</title> <script> /*var a = 5; var b = a; b += 3; alert(b); //8 alert(a); //5 */ //物件和函式和陣列都是引用的關係 /*var a = [1,2,3]; var b = a; b.push(4); alert(b); //1,2,3,4 alert(a); //1,2,3,4*/ var a = [1,2,3]; var b = a; b = [1,2,3,4]; alert(b); //1,2,3,4 alert(a); //1,2,3
</script> </head> <body> </body> </html>
淺層拷貝:
function simpleClone(initalObj) {
var obj = {};
for ( var i in initalObj) {
obj[i] = initalObj[i];
}
return obj;
}
var obj = { a: "hello", b:{ a: "world", b: 21 }, c:["Bob", "Tom", "Jenny"], d:function() { alert("hello world"); } }
var cloneObj = simpleClone(obj); console.log(cloneObj.b); console.log(cloneObj.c); console.log(cloneObj.d); cloneObj.b.a = "changed"; cloneObj.c = [1, 2, 3]; cloneObj.d = function() { alert("changed"); }; console.log(obj.b);//淺拷貝 改動一個物件的值,另一個還是會受到影響 淺拷貝其實就是簡單的複製第一層,深層的改變依然會受影響 console.log(obj.c); console.log(obj.d);
深拷貝:直接上個比較完善的方法,不會出問題的:(遞迴拷貝)
function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用物件導致死迴圈,如initalObj.a = initalObj的情況 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : {}; deepClone(prop, obj[i]); } else { obj[i] = prop; } } return obj; } var str = {}; var obj = { a: {a: "hello", b: 21} }; deepClone(obj, str); obj.a=1; console.log(str.a);//{a: "hello", b: 21} 互不影響 console.log(str.a.a)//hello console.log(obj);//{a: 1}使用Object.create()方法,也可以達到深層拷貝
直接使用var newObj = Object.create(oldObj),可以達到深拷貝的效果。
function deepClone(initalObj, finalObj) {
var obj = finalObj || {};
for (var i in initalObj) {
var prop = initalObj[i]; // 避免相互引用物件導致死迴圈,如initalObj.a = initalObj的情況
if(prop === obj) {
continue;
}
if (typeof prop === 'object') {
obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
} else {
obj[i] = prop;
}
}
return obj;
}