咱們都知道:在計算機領域中,堆棧是兩種數據結構,它們只能在一端(稱爲棧頂(top))對數據項進行插入和刪除。javascript
JavaScript的數據類型分爲兩大種:
1. 基本類型:Undefined、Null、Boolean、Number 和 String,這5中基本數據類型能夠直接訪問,他們是按照值進行分配的,存放在棧(stack)內存中的簡單數據段,數據大小肯定,內存空間大小能夠分配。
2. 引用類型:即存放在堆(heap)內存中的對象,變量實際保存的是一個指針,這個指針指向另外一個位置。
以上咱們知道了什麼是堆棧,和JavaScript的數據類型,下面咱們根據js的數據類型來講明一下他們的拷貝狀況:java
結合下面的例子理解堆棧的關係:程序員
var xm = { age: 18, score: 4 }; var xh = { age: 18, score: 4 }; console.log(xm===xh); //false var newobj=xh console.log(newobj===xh); //true //下面這也是一個你叫經典的例子能夠試一下 function setName(obj) { obj.name = 'xm'; //在傳參數中新建內存對象,而且設定一個值 obj = {}; //對象是引用類型。系統在堆中新建一個內存空間,與傳入值無關。 obj.name = 'xh'; //在新建的內存空間設置一個值(與傳入值是獨立開來的。) } var person = {}; setName(person); console.log(person.name); // xm //console.log([] instanceof Array); // console.log(typeof []);
xm和xh的對象值是同樣的,但是在關係比較重爲false,當新建對象賦值是這種狀況就是true.下圖給你們講解。數據結構
這就會出現另一種狀況,咱們想去判斷引用類型的值是否相等,(下面以對象爲例子進行講解。)函數
var xm = { age: 18, score: 4 }; var xh = { age: 18, score: 4 }; function equalObjs(a, b) { for (var p in a) { if (a[p] !== b[p]) return false; } return true; }
基本類型拷貝的時候只是在內存中又開闢了新的空間,是的新建的值與拷貝值相互獨立。(能夠理解爲在堆中新建一個空間存放一樣的值。)這個方法能夠利用上面判斷相等的辦法遍歷出堆(heap)值從新賦值。所以深淺拷貝是相對於引用類型的。spa
var xm = { age: 18, score: 4, arr1:[1,32] }; function copyObj(obj) { var newObj = {}; for (var p in obj) { newObj[p] = obj[p]; } return newObj; } var xh = copyObj(xm); // var arr1=[1,2,3] xh.arr1.push(33) console.log(xh) //{age: 18, score: 4, arr1: Array(3)} console.log(xh===xm); //false console.log(xh.arr1===xm.arr1); //true
console.log(xh.arr1===xm.arr1); //true 這裏出現了一個問題,淺拷貝中遍歷對象裏面包含了另一個應用類型(arr1),而它的空間是獨立的,這樣直接被引用。指針
若是想實現兩個值的徹底獨立,這時就須要使用到深拷貝。code
根據淺拷貝出現的問題,咱們可使用深拷貝的方法解決問題。對象
深拷貝的方法比較多,我舉一些比較簡單的例子來講明一下。blog
最簡單的辦法:JSON.parse(obj)
var xm = { age: 18, score: 4, arr1:[1,32] }; var xh=JSON.parse(JSON.stringify(xm)) xh.arr1.push(33) console.log(xh) //{age: 18, score: 4, arr1: Array(3)} console.log(xh===xm); //false console.log(xh.arr1===xm.arr1); //false
其餘的方法須要使用遞歸操做來進行。