var obj = {
	name: 'Lance',
  age: 28,
  say() {
  	console.log('Hello');
  },
  a: {
  	b: {
    	c: 233
    }
  }
}

ES5

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;
}

WeakMap & Map & Object

Map 键名 -> 任意类型 {}、[]都行

{} 键名 -> 字符串

WeakMap 键名 -> 只能是对象

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 中键名的对象,在外界没有被引用了,就会被回收,同时一并的把相应的键值也给回收了。

ES6

前置知识

undefined == null