1. 程式人生 > >js中值的基本型別與引用型別,以及物件引用,物件的淺拷貝與深拷貝

js中值的基本型別與引用型別,以及物件引用,物件的淺拷貝與深拷貝

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"
> <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

var obj={}; var objcopy=obj; objcopy.fun=function(){ console.trace(); console.log('obi.fun'); }; obj.fun();//obi.fun同樣會執行objcopy新增的fun方法,證明倆人是引用的同樣的東東

</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;
}