克隆的实现
浅克隆
浅克隆,只是最外面的部分被克隆,深层的对象依然是引用指向被克隆对象的同一块堆内存,所以存在的问题就是,当被克隆的对象或者新对象发生修改,两个对象会同时被修改。新的api Object.assign()也有同样的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const oldObj = { a: 1, b: ['d','e'], c: { f: {g: 2} } };
function shallowClone(o){ const obj = {}; for(let i in o){ obj[i] = o[i]; } return obj; };
let newObj = shallowClone(oldObj); console.log(oldObj === newObj); console.log(oldObj.c.f === newObj.c.f);
newObj.a = 'change'; console.log(oldObj.a, newObj.a);
newObj.c.f.g = 'change'; console.log(oldObj.c.f.g, newObj.c.f.g);
|
深度克隆
1 2 3 4 5 6 7
| const oldObj = { a: 1, b: ['d','e'], c: { f: {g: 2} } };
const newObj = JSON.parse(JSON.stringify(oldObj));
|
通过上面JSON的parse和stringify看似可以达到深度克隆的效果,但其中却是有坑的。
- 它无法实现对函数、RegExp等特殊对象的克隆
- 会抛弃对象的constructor,所有的构造函数会指向Object
- 对象有循环引用,会报错
对于深度克隆,需要判断对象的类型,来针对相应的类型应用相应的克隆方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| const isType = (obj, type) => { if (typeof obj !== 'object') return false; const typeString = Object.prototype.toString.call(obj); let flag; switch (type) { case 'Array': flag = typeString === '[object Array]'; break; case 'Date': flag = typeString === '[object Date]'; break; case 'RegExp': flag = typeString === '[object RegExp]'; break; default: flag = false; } return flag; };
const clone = parent => { const parents = []; const children = [];
const _clone = parent => { if (parent === null) return null; if (typeof parent !== 'object') return parent;
let child, proto;
if (isType(parent, 'Array')) { child = []; } else if (isType(parent, 'RegExp')) { child = new RegExp(parent.source, getRegExp(parent)); if (parent.lastIndex) child.lastIndex = parent.lastIndex; } else if (isType(parent, 'Date')) { child = new Date(parent.getTime()); } else { proto = Object.getPrototypeOf(parent); child = Object.create(proto); }
const index = parents.indexOf(parent);
if (index != -1) { return children[index]; } parents.push(parent); children.push(child);
for (let i in parent) { child[i] = _clone(parent[i]); }
return child; }; return _clone(parent); };
|
请针对 Disqus 开启代理