We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案 欢迎大家在下方发表自己的优质见解 二维码加载失败可点击 小程序二维码
看个例子
function deepCopy(obj) { const res = Array.isArray(obj) ? [] : {}; for (let key in obj) { if (typeof obj[key] === "object") { res[key] = deepCopy(obj[key]); } else { res[key] = obj[key]; } } return res; } var obj = { a: 1, b: 2, c: [1, 2, 3], d: { aa: 1, bb: 2 }, }; obj.e = obj; console.log("obj", obj); // 不会报错 const objCopy = deepCopy(obj); console.log(objCopy); //Uncaught RangeError: Maximum call stack size exceeded
从例子可以看到,当存在循环引用的时候,deepCopy 会报错,栈溢出。
大家都知道,对象的 key 是不能是对象的。
{{a:1}:2} // Uncaught SyntaxError: Unexpected token ':'
参考解决方式一:使用 weekmap:
解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系
这个存储空间,需要可以存储key-value形式的数据,且key可以是一个引用类型,
key-value
key
我们可以选择 WeakMap 这种数据结构:
WeakMap
value
function isObject(obj) { return (typeof obj === "object" || typeof obj === "function") && obj !== null; } function cloneDeep(source, hash = new WeakMap()) { if (!isObject(source)) return source; if (hash.has(source)) return hash.get(source); // 新增代码,查哈希表 var target = Array.isArray(source) ? [] : {}; hash.set(source, target); // 新增代码,哈希表设值 for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { if (isObject(source[key])) { target[key] = cloneDeep(source[key], hash); // 新增代码,传入哈希表 } else { target[key] = source[key]; } } } return target; }
参考解决方式二:
可以用 Set,发现相同的对象直接赋值,也可用 Map
const o = { a: 1, b: 2 }; o.c = o; function isPrimitive(val) { return Object(val) !== val; } const set = new Set(); function clone(obj) { const copied = {}; for (const [key, value] of Object.entries(obj)) { if (isPrimitive(value)) { copied[key] = value; } else { if (set.has(value)) { copied[key] = { ...value }; } else { set.add(value); copied[key] = clone(value); } } } return copied; }
The text was updated successfully, but these errors were encountered:
function deepCloneObj(obj) { if(obj == null) return obj; const o = Object.assign({}, obj); Object.keys(o).forEach(k => { const v = o[k]; if(Object.prototype.toString.call(v) == '[object Object]') { // 如果是循环引用,会造成递归爆栈,使用set集合装对象,如果有相同的对象直接返回 const set = Object.prototype.toString.call(deepCloneObj[Symbol.for('cache')]) == "[object Set]" ? deepCloneObj[Symbol.for('cache')] : deepCloneObj[Symbol.for('cache')] = new Set(); if(set.has(v)) { o[k] = v; }else{ set.add(v); o[k] = deepCloneObj(v); } }else if(Object.prototype.toString.call(v) == '[object Array]') { o[k] = deepCloneArr(v); function deepCloneArr(arr) { const tmp = []; for(let i = 0; i < arr.length; i++) { const item = arr[i]; if(Object.prototype.toString.call(item) == '[object Object]') { tmp.push(deepCloneObj(item)); }else if(Object.prototype.toString.call(item) == '[object Array]') { tmp.push(deepCloneArr(item)); }else { tmp.push(item) } } return tmp; } } }) return o; } var obj = { a: 1, b: 2, c: [1, 2, 3], d: { aa: 1, bb: 2 }, }; obj.e = obj; deepCloneObj(obj);
Sorry, something went wrong.
var test1 = { a: { a: 'a' } }; test1.z = test1; var test2 = clone(test1); test2.z.z.a.a = 'z'; console.log(test1.a.a); // 会输出 'z',但不是应该输出'a'吗
No branches or pull requests
扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。
循环引用问题
看个例子
从例子可以看到,当存在循环引用的时候,deepCopy 会报错,栈溢出。
循环应用问题解决
大家都知道,对象的 key 是不能是对象的。
参考解决方式一:使用 weekmap:
解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系
这个存储空间,需要可以存储
key-value
形式的数据,且key
可以是一个引用类型,我们可以选择
WeakMap
这种数据结构:WeakMap
中有无克隆过的对象key
,克隆对象作为value
进行存储参考解决方式二:
可以用 Set,发现相同的对象直接赋值,也可用 Map
The text was updated successfully, but these errors were encountered: