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
首先来直观的感受一下什么是拷贝。
const arr = [1, 2, 3]; const newArr = arr; newArr[0] = 100; console.log(arr); // [100, 2, 3]
这是直接赋值的情况,不涉及任何拷贝。当改变 newArr 的时候,由于是同一个引用,arr 指向的值也跟着改变。
现在进行浅拷贝:
const arr = [1, 2, 3]; const newArr = arr.slice(); newArr[0] = 100; console.log(arr); //[1, 2, 3]
当修改 newArr 的时候,arr 的值并不改变。什么原因?因为这里 newArr 是 arr 浅拷贝后的结果,newArr 和 arr 现在引用的已经不是同一块空间啦!
这就是浅拷贝!但是这又会带来一个潜在的问题:
const arr = [1, 2, { val: 4 }]; const newArr = arr.slice(); newArr[2].val = 1000; console.log(arr); // [ 1, 2, { val: 1000 } ]
当我们改变了 newArr 改变了第二个元素的 val 值,arr 也跟着变了。
这就是浅拷贝的限制所在了。它只能拷贝一层对象。如果有对象的嵌套,那么浅拷贝将无能为力。 深拷贝就是为了解决这个问题而生的,它能解决无限极的对象嵌套问题,实现彻底的拷贝。
Object.assign({}, ...sources)
...
[...arr]
{...obj}
[].concat(arr)
arr.slice()
const shallowClone = (target) => { if (typeof target === 'object' && target !== null) { const cloneTarget = Array.isArray(target) ? [] : {}; for (let prop in target) { if (target.hasOwnProperty(prop)) { cloneTarget[prop] = target[prop]; } } return cloneTarget; } else { return target; } };
JSON.parse
JSON.stringify
使用JSON.parse(JSON.stringify())能覆盖大多数的应用场景所需要的深拷贝,但是它也有许多问题:
JSON.parse(JSON.stringify())
RegExp
Date
Set
Map
Function
undefined
关于 JSON.stringify 的坑可以看看这一篇文章 https://juejin.im/post/6844904016212672519 。
关于循环引用的例子:
首先写一个不考虑循环引用的普通深拷贝:
const deepClone = (target) => { if (typeof target === 'object' && target !== null) { const cloneTarget = Array.isArray(target) ? [] : {}; for (let prop in target) { if (target.hasOwnProperty(prop)) { cloneTarget[prop] = deepClone(target[prop]); } } return cloneTarget; } else { return target; } };
创建一个 cache,用来记录下已经拷贝过的对象,若已经拷贝过,直接返回。
function deepCopy(obj, cache = new WeakMap()) { if (obj === null || typeof obj !== 'object') return obj; if (cache.has(obj)) return cache.get(obj); const copy = Array.isArray(obj) ? [] : {}; cache.set(obj, copy); Object.keys(obj).forEach(key => { copy[key] = deepCopy(obj[key], cache); }); return copy; }
结构化克隆算法(Structured Cloning Algorithm)
The text was updated successfully, but these errors were encountered:
Object.getOwnPropertyDescriptors
Object.create
Reflect.ownKeys
Object.keys
function deepCopy(obj, cache = new WeakMap()) { if (obj === null || typeof obj !== 'object') return obj; if (obj.constructor === Date) return new Date(obj); if (obj.constructor === RegExp) return new RegExp(obj); if (cache.has(obj)) return cache.get(obj); const descs = Object.getOwnPropertyDescriptors(obj); const copy = Object.create(Object.getPrototypeOf(obj), descs); cache.set(obj, copy); Reflect.ownKeys(obj).forEach(key => { copy[key] = deepCopy(obj[key], cache); }); return copy; }
Sorry, something went wrong.
No branches or pull requests
什么是拷贝?
首先来直观的感受一下什么是拷贝。
这是直接赋值的情况,不涉及任何拷贝。当改变 newArr 的时候,由于是同一个引用,arr 指向的值也跟着改变。
现在进行浅拷贝:
当修改 newArr 的时候,arr 的值并不改变。什么原因?因为这里 newArr 是 arr 浅拷贝后的结果,newArr 和 arr 现在引用的已经不是同一块空间啦!
这就是浅拷贝!但是这又会带来一个潜在的问题:
当我们改变了 newArr 改变了第二个元素的 val 值,arr 也跟着变了。
这就是浅拷贝的限制所在了。它只能拷贝一层对象。如果有对象的嵌套,那么浅拷贝将无能为力。
深拷贝就是为了解决这个问题而生的,它能解决无限极的对象嵌套问题,实现彻底的拷贝。
浅拷贝的实现
Object.assign({}, ...sources)
...
扩展运算符(spread),如[...arr]
、{...obj}
[].concat(arr)
- 拷贝数组arr.slice()
- 拷贝数组深拷贝的实现
JSON.parse
和JSON.stringify
使用
JSON.parse(JSON.stringify())
能覆盖大多数的应用场景所需要的深拷贝,但是它也有许多问题:RegExp
、Date
、Set
、Map
、Function
……undefined
的 key 会丢失关于
JSON.stringify
的坑可以看看这一篇文章 https://juejin.im/post/6844904016212672519 。关于循环引用的例子:
递归
首先写一个不考虑循环引用的普通深拷贝:
解决循环引用
创建一个 cache,用来记录下已经拷贝过的对象,若已经拷贝过,直接返回。
结构化克隆算法(Structured Cloning Algorithm)
The text was updated successfully, but these errors were encountered: