幾個例子理解淺拷貝和深拷貝


一、內存的堆棧

  1. 基本類型
    存放在棧內存中的簡單數據段,數據大小確定,內存空間大小可以分配,當它賦給另一個變量的時候,另一個變量發生改變,原數據不會發生改變:
  var a = 5;
  var b = a;
  b += 1;
  console.log(b)  //6
  console.log(a)  //5

5種基本數據類型有Undefined、Null、Boolean、Number 和 String,它們是直接按值存放的,所以可以直接訪問。

  1. 引用類型
    存放在堆內存中的對象,變量實際保存的是一個指針,這個指針指向另一個位置。每個空間大小不一樣,要根據情況進行特定的分配。當我們需要訪問引用類型(如對象,數組,函數等)的值時,首先從棧中獲得該對象的地址指針,然后再從堆內存中取得所需的數據。
  var a = { userName : 'undefined' };
  var b = a;
  b.userName = 'xiaoming';
  console.log(a);  //{userName: "xiaoming"}
  console.log(b);  //{userName: "xiaoming"}

上面的例子把a的值賦值給b,當b的值發生改變的時候,a的值也會跟隨改變,像上面的圖解一樣,a和b都是指向同一個地址。如果要讓b得到一個獨立的地址呢?這就涉及到拷貝了。

二、Object.assign

淺拷貝是復制淺層的引用類型,比如復制a = { userName : 'undefined' }這樣的對象就是屬於淺拷貝,它只有一層,像復制b = { info : { userName : 'undefined' } }這樣有嵌套的對象,多層的引用類型,就需要用到深拷貝了。

  • Object.assign()方法可以得到一份淺拷貝的引用類型
  var a = { userName : 'undefined' };
  var b = Object.assign({} , a);
  b.userName = 'xiaoming';
  console.log(a);  //{userName: "undefined"}
  console.log(b);  //{userName: "xiaoming"}

這樣,我們就能得到一份淺拷貝內容了,即使是b發生改變,也不會影響到a,它們完全是兩個獨立的個體,但是此方法不適用深拷貝。

三、展開運算符

  • 利用展開運算符方法也可以得到一份淺拷貝的引用類型:
  var a = { userName : 'undefined' };
  var b = {...a};
  b.userName = 'xiaoming';
  console.log(a);  //{userName: "undefined"}
  console.log(b);  //{userName: "xiaoming"}

這樣,我們也能得到一份淺拷貝內容。

四、JSON.parse()&JSON.stringify()

  • 利用JSON下面的parse()方法和stringify()方法可以得到一份深拷貝內容,stringify()方法可以把對象轉變成json格式的字符串,再通過parse()方法進行轉譯成對象來獲得一份拷貝的對象(當然淺拷貝也是適用的):
  var a = { info:{userName : 'undefined'}};
  var b = JSON.parse(JSON.stringify(a));
  b.info.userName = 'xiaoming';
  console.log(a);  // { info:{userName : 'undefined'}};
  console.log(b);  // { info:{userName : 'xiaoming'}};

五、for...in&遞歸(推薦)

  • 這種方法適用於任何引用類型,原理是使用for..in循環,配合遞歸函數實現深層拷貝 :
		var a = { info:{userName : 'undefined'}};
		var b = copy(a);
		b.info.userName = 'xiaoming'
		function copy(obj){
			var result = {};
			for(var attr in obj){
				if( typeof obj[attr] === 'object' ){
					result[attr] = copy(obj[attr]);
				}
				else{
					result[attr] = obj[attr];
				}
			}
			return result;
		}

		console.log(a);   // { info:{userName : 'undefined'}};
		console.log(b);   //{userName: "xiaoming"}

這樣,就可以得到一份深拷貝內容了,其原理就是層層拷貝,利用遞歸的原理,直到最底層不是對象為止,好啦,本次分享就到這里了,如果有什么不正確的地方,請各位不吝賜教,謝謝~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM