淺複製與深複製
1. 淺複製
淺複製最大的特點就是對於對象,只複製對象引用
一. Object.assign(),對象融合
var a = {
prop: 'haha',
hello: 'Hi world',
obj: {
inner: 'yes'
}
}
var b = Object.assign({}, a);
a.obj === b.obj; // true
二. spread操作符
var c = {...a};
a.obj === c.obj; // true
三. for-in遍歷
function clone(obj){
var result = {};
for(let p in obj){
result[p] = obj[p];
}
return result;
}
var d = clone(a);
a.obj === d.obj; // true
2. 深拷貝
一. JSON方法
注意遇到函數和值爲undefined的屬性會被自動忽略(還有Symbol)
var a = {
prop: 'haha',
hello: 'Hi world',
obj: {
inner: 'yes'
},
udf: undefined,
nul: null,
fun: function(t){return t;}
}
var b = JSON.stringify(a);
b = JSON.parse(b);
// b.udf 和 b.fun 屬性丟失了
a.obj === b.obj; // false
二. 遞歸遍歷
- 處理常見的數組和普通對象
- for-in遍歷的話會丟棄不可枚舉屬性
- 使用hasOwnProperty過濾原型屬性
function deepClone(obj){
// 基本值
if(typeof obj !== 'object' || obj === null){
return obj;
}
// 複雜值
var result = Array.isArray(obj) ? [] : {};
for(let p in obj){
if(obj.hasOwnProperty(p)){
result[p] = deepClone(obj[p]);
}
}
return result;
}
var b = deepClone(a);
b.obj === a.obj; // false
- 出現循環引用的話,要用的
weakMap
; - 對於
Date
、RegExp
等使用Object.prototype.toString.call()
深度區分