深浅拷贝概念及手写实现 | 刷题打卡
分类:javascript
一、概念:什么是深浅拷贝?
- 浅拷贝:对象的自有属性中仅仅拷贝基础类型,复杂类型只是引用而不去遍历。
- 深拷贝:遍历对象自有属性,如果发现属性中存在对象那就继续深入遍历。
let obj = {
name: 'Steven Lee',
props: {
static: true
}
}
举个简单的栗子,分别用深浅拷贝两种方式复制一份上方代码中的obj对象,深浅拷贝对象中修改obj.name都不会对原对象造成影响;浅拷贝对象修改obj.props.static
会导致原对象也发生变化(只是引用关系),而深拷贝是额外开辟了内存空间所以修改深拷贝的结果对原对象不会造成影响。
二、实现
1.浅拷贝
遍历第一层对象赋值即可
- 标准实现
function shallowCopy(obj) {
if (typeof obj !== 'object') return
let newObj = obj instanceof Array ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key]
}
}
return newObj
}
- es6 简单实现
真的很简单
let shallowCopyObj = {...obj}
2.深拷贝
遍历对象,属性中发现对象就继续遍历
- 标准实现
function deepClone(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key];
}
}
return newObj;
}
- 简单实现
JSON.parse(JSON.stringify(obj))
当然,以上两种方式都没有考虑对象属性中存在内置对象和函数的问题。
一般来说,我们使用JSON.parse(JSON.stringify(obj))
就可以解决大多数的问题了,如果还不能满足需求那就要用到JSON.stringify
的第二个参数进行特殊处理,举个例子
JSON.stringify({ a: 1, b: 2,c: undefined }) // "{"a":1,"b":2}"
function fn(key, value) {
if (typeof value === "undefined") {
value = 'undefined';
}
return value;
}
JSON.stringify({ a: 1, b: 2, c: undefined }, fn) // "{"a":1,"b":2,"c":"undefined"}"
同理,我们也可以新加一些内置对象的判断和适配。