ES6深拷贝函数封装 |
您所在的位置:网站首页 › js深拷贝拷贝函数 › ES6深拷贝函数封装 |
前置:WeakMap数据类型
Map与WeakMap区别: Map的键名可以是任意类型({}、[]) WeakMap的键名只能是对象例:从垃圾回收来感受WeakMap const oBtn1 = document.querySelector('#btn1') const oBtn2 = document.querySelector('#btn1') oBtn1.addEventListener('click', handleClick1, false) oBtn2.addEventListener('click', handleClick2, false) function handleClick1() {} function handleClick2() {} oBtn1.remove() // 删除节点,但是不能回收事件回调函数 oBtn2.remove() // 必须使用这种方法删除回调 handleClick1 = null; handleClick2 = null使用WeakMap: const oBtn1 = document.querySelector('#btn1') const oBtn2 = document.querySelector('#btn1') const oBtnMap = new WeakMap() // 将节点与回调绑定在一起,垃圾回收时一起被回收(键名键值一起回收) // 键名是弱引用 oBtnMap.set(oBtn1, handleClick1) oBtnMap.set(oBtn2, handleClick2) oBtn1.addEventListener('click', handleClick1, false) oBtn2.addEventListener('click', handleClick2, false) function handleClick1() {} function handleClick2() {} // oBtn1.remove() // 删除节点,但是不能回收事件回调函数 //oBtn2.remove()换一个角度看,WeakMap的键名必须是对象,弱引用才有意义。 深拷贝函数封装拷贝之前,需要先判断原始值(origin)的数据类型再进行下一步操作。 function当做静态数据类型,不做特殊处理。 1)关于null和undefined的判断: // null undefined var a = undefined; console.log(a == null); // true console.log(a === null); // false使用 origin === undefined 表达式就能判断origin是否为null和undefined值。 2)判断Date、RegExp类型数据: if (origin instanceof Date) { return new Date(origin); } if (origin instanceof RegExp) { return new RegExp(origin); }3)判断 {} 或 [] : 使用构造器 const obj = {} console.log(obj)打印结果: 可以看到,字面量obj是通过其原型上的constructor使用new Object构造出来的,那么是否可以自己手动构造一个obj呢? const obj = {} const newObj = new obj.constructor() console.log(obj) // {} newObj.a = 1 console.log(newObj); // {a:1}同理,数组: const arr = [] const newArr = new arr.constructor() console.log(arr); newArr.push(1) console.log(newArr);知道这点,直接使用 const target = new origin.constructor() 生成一个新 {} 或 [] 即可,不用再判断了。 封装函数1 function deepClone(origin) { if (origin === undefined || typeof origin !== 'object') { // 排除null、undefined、非object值 return origin; } if (origin instanceof Date) { return new Date(origin); } if (origin instanceof RegExp) { return new RegExp(origin); } // [] -> [], {} -> {}, 不需要判断是对象还是数组 const target = new origin.constructor() for (let k in origin) { if (origin.hasOwnProperty(k)) { target[k] = deepClone(origin[k]) } } return target; } 测试1 var obj = { name: 'yesmore', age: 18, info: { hobby: ['travel', 'piano', { a: 1 }], career: { teacher: 4, engineer: 9 } } }; const newObj = deepClone(obj) newObj.info.hobby[2].a = 1234 console.log(newObj);结果: 原因:test1和test2分别作为属性值赋值给对方,在拷贝时,会发生重复拷贝,简而言之,就是缺少记录是否拷贝。 解决:使用 hashMap 哈希表方式记录键名是否存在,通过 WeakMap 实现。 封装函数2 function deepClone(origin, hashMap = new WeakMap()) { if (origin === undefined || typeof origin !== 'object') { // 排除null、undefined、非object值 return origin; } if (origin instanceof Date) { return new Date(origin); } if (origin instanceof RegExp) { return new RegExp(origin); } const hashKey = hashMap.get(origin); // 寻找键是否存在 if (hashKey) { return hashKey } // [] -> [], {} -> {}, 不需要判断是对象还是数组 const target = new origin.constructor() hashMap.set(origin, target) for (let k in origin) { if (origin.hasOwnProperty(k)) { target[k] = deepClone(origin[k], hashMap) } } return target; } 测试3 let test1 = {} let test2 = {} test2.test1 = test1 test1.test2 = test2 console.log(deepClone(test2));结果: 同系列文章请查看:【Github】pre-interview |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |