深拷貝:一個變量複製另一個變量的內容,但兩個變量之間相互不影響。用通俗的話說就是兩個變量只是長的一樣,但是不是同一個人。
有深拷貝當然也就會有淺拷貝,淺拷貝比較簡單,一個變量複製另一個變量的內容,這個變量是另一個變量的副本。其實倆變量都是同一個人,只是名字不同,有兩個名字。
深拷貝的主要應用在引用值的數據類型,像數組、對象的等。這裏還牽扯到一個知識點,就是如何區分變量是數組對象還是對象。換句話需要判斷變量是[ ]還是{ }。因爲在JavaScript中的Array和Object都是對象。
區分Array和Object
var arr = [];
var obj = {};
- instanceof 標識符
a instanceof b
看a的原型鏈上是否有b的原型
console.log(obj instanceof Object);
console.log(arr instanceof Object);
console.log(obj instanceof Array);
- toString()方法
console.log(Object.prototype.toString.call(obj));
console.log(Object.prototype.toString.call(arr));
- constructor屬性
封裝深拷貝函數
在上面結束了這些之後,我們再來看怎麼去實現深層拷貝。
分析:
- 遍歷對象
- 判斷對象的屬性是不是基本類型值 是——直接複製
- 複雜數據類型需要判斷是 {} 還是 [] 創建不同的對象
- 遞歸 再一次把對象的屬性值作爲被拷貝對象 進行拷貝
- 直到遇到基本數據類型值遞歸結束
var obj = {
name: 'lyf',
age: 18,
card: ['visa', 'master'],
wife: {
name: 'xxx',
age: 18
}
}
var objCopy = {};
deepClone(objCopy, obj);
// target拷貝origin對象
function deepClone(target, origin) {
// 初始化變量
var target = target || {},
arrStr = "[object Array]",
toStr = Object.prototype.toString;
for (prop in origin) {
// 判斷origin對象的屬性是不是自己的 不用拷貝原型上的屬性和方法
if (origin.hasOwnProperty(prop)) {
// 判斷對象值是引用值類型還是數值類型
if (origin[prop] !== "null" && typeof (origin[prop]) == "object") {
// if (toStr.call(origin[prop]) == arrStr) {
// target[prop] = [];
// } else {
// target[prop] = {};
// }
// 優化
target[prop] = toStr.call(origin[prop]) == arrStr ? [] : {};
} else {
target[prop] = origin[prop];
}
}
}
return target;
}
當我們爲任意一個對象添加值時,都不會互相影響。
深拷貝結束!!!!