导航
var obj = {
name: 'Lance',
age: 28,
say() {
console.log('Hello');
},
a: {
b: {
c: 233
}
}
}
function deepClone(obj) {
// 处理 null 或者 undefined
if (obj === null || typeof obj !== 'object') {
return obj;
}
// 处理数组
if (Array.isArray(obj)) {
var arrCopy = [];
for (var i = 0; i < obj.length; i++) {
arrCopy[i] = deepClone(obj[i]);
}
return arrCopy;
}
// 处理普通对象
var objCopy = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
objCopy[key] = deepClone(obj[key]);
}
}
return objCopy;
}
Map 键名 -> 任意类型 {}、[]都行
{} 键名 -> 字符串
WeakMap 键名 -> 只能是对象
const oBtn1 = document.querySelector('#btn1');
const oBtn2 = document.querySelector('#btn2');
oBtn1.addEventListener('click', handleBtn1Click, false);
oBtn2.addEventListener('click', handleBtn2Click, false);
function handleBtn1Click() {}
function handleBtn2Click() {}
// 某些场景下需要删除btn
oBtn1.remove();
oBtn2.remove();
// 而此刻 handleBtn1Click 不会被销毁,理论上需要手动销毁
handleBtn1Click = null;
handleBtn2Click = null;
有了 WeakMap 就可以这样做:
const oBtnMap = new WeakMap();
oBtnMap.set(oBtn1, handleBtn1Click);
oBtnMap.set(oBtn2, handleBtn2Click);
oBtn1.addEventListener('click', oBtnMap.get(oBtn1), false);
oBtn2.addEventListener('click', oBtnMap.get(oBtn2), false);
oBtn1.remove();
oBtn2.remove();
WeakMap 是弱引用,一旦 oBtn1 被 remove 掉,它就会被回收。所以这也解释了为什么 WeakMap 的键名要是个对象类型。
oBtn1 都被回收了,相应的键值 handleBtn1Click 也会被回收
WeakMap 中键名的对象,在外界没有被引用了,就会被回收,同时一并的把相应的键值也给回收了。
undefined == null
trueundefined === null
falsevar a = undefined;
a == null; // true
a === undefined; // true
var arr = [];
var newArr = new arr.constructor();
newArr.push(1);
console.log(arr);
console.log(newArr);
var obj = {};
var newObj = new obj.constructor();
newObj.name = 'Lance';
console.log(obj);
console.log(newObj);
function deepClone(source) {
if (source == undefined || typeof source !== 'object') {
return source;
}
if (source instanceof Date) {
return new Date(source);
}
if (source instanceof RegExp) {
return new RegExp(source);
}
// 创建一个和源对象一样的空对象
const target = new source.constructor();
// 然后把源对象中自身可枚举属性一个个填入空对象
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = deepClone(source[key]);
}
}
return target;
}
var test1 = {};
var test2 = {};
test1.test2 = test2;
test2.test1 = test1;
function deepClone(source, hashMap = new WeakMap()) {
if (source == undefined || typeof source !== 'object') {
return source;
}
if (source instanceof Date) {
return new Date(source);
}
if (source instanceof RegExp) {
return new RegExp(source);
}
const hasItem = hashMap.get(source);
if (hasItem) return hasItem;
const target = new source.constructor();
hashMap.set(source, target);
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = deepClone(source[key], hashMap);
}
}
return target;
}
console.log(deepClone(test2));