複習到深淺拷貝問題,簡單Mark一下實現方法。函數
## 寫在前面ui
首先咱們得清楚基本概念。拷貝(Copy)即複製。spa
淺拷貝:建立一個新對象,保存原始對象屬性值精準拷貝。若是屬性是基本類型,拷貝的是基本類型的值,若是屬性是引用類型,拷貝的是內存地址,並不會佔用新的內存,這種狀況下若是其中一個對象改變了這個地址,會影響到另外一個對象。淺拷貝只複製指向某個對象的指針,而不復制對象自己。**新舊對象共享同一塊內存**。prototype
深拷貝:將一個對象從內存中完整的拷貝一份出來,從堆內存中開闢一個新的區域存放新對象,增長了內存,且修改新對象不會影響原對象。**新對象與原對象不共享內存**。指針
## 賦值和深/淺拷貝的區別(針對引用類型)code
賦值:把一個對象賦值給一個新的變量時,賦的實際上是該對象的在棧中的地址,而不是堆中的數據。對象
淺拷貝:從新在堆中建立內存,拷貝先後對象的基本數據類型互不影響,但拷貝先後對象的引用類型因共享同一塊內存,會相互影響。blog
深拷貝:從堆內存中開闢一個新的區域存放新對象,對對象中的子對象進行遞歸拷貝,先後的兩個對象互不影響。遞歸
## 淺拷貝的實現方案內存
### 0x01 Object.assign()
把任意多個源對象自身的可枚舉屬性拷貝給目標對象,而後返回目標對象。
let obj2 = Object.assign({}, obj1)
### 0x02 函數庫lodash的_.clone方法
var _ = require('lodash'); var obj2 = _.clone(obj1);
### 0x03 展開運算符
同object.assign()功能相同
let obj2 = {...obj1}
### 0x04 Array.prototype.concat()
let arr2 = arr1.concat()
### 0x05 Array.prototype.slice()
let arr2 = arr1.slice()
## 深拷貝的實現方案
### 0x01 JSON.parse()和JSON.stringify()
let arr2 = JSON.parse(JSON.stringify(arr1));
缺點是不能處理函數和正則
### 0x02 函數庫lodash的_.cloneDeep方法
var _ = require('lodash'); var obj2 = _.cloneDeep(obj1);
### 0x03 jQuery.extend()方法
$.extend(deepCopy,target,obj1,[objN]) // 第一個參數爲true就是深拷貝
### 0x04 手寫遞歸實現
解決循環引用的問題
function deepClone(obj, hash=new WeakMap()) { if(obj == null) return obj; // 不操做 if(obj instanceof Date) return new Date(obj); if(obj instanceof RegExp) return new RegExp(obj); // 普通值/函數不須要深拷貝 if(typeof obj !== "object") return obj; // 是對象的話要進行深拷貝 if(hash.get(obj)) return hash.get(obj); let cloneObj = new obj.constructor(); // 找到的是所屬類原型上的constructor,而原型上的constructor指向的是當前類自己 hash.set(obj. cloneObj); for(let key in obj) { if(obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key], hash) } } return cloneObj; }