测试数据
let obj = {
a: 1,
b: 'b',
c: null,
d: undefined,
e: { a: { b: 1 } },
f: [1, 2],
g: function () { console.log(1) },
h: /cc/ig,
i: new Date(),
}
浅拷贝
浅拷贝:创建一个对象,复制属性。其中引用类型的属性复制的为地址。
// 方式1
// 实现浅拷贝,并追加{d:3}
let obj2 = Object.assign({}, obi, { d: 3 })
// 方式2
// 展开运算符
let obj3 = {...obj1}
深拷贝
深拷贝:复制整个对象,其中引用类型的属性复制的为值,拷贝后的两个对象是两个独立的个体
简易深拷贝:
- 数组、普通对象{}、基本数据类型
- 不考虑循环引用
// 判断是否是引用类型
function isObject(val) {
return val !== null && (typeof val === 'object' || typeof val === 'function')
}
function deepClone1(source) {
if (!isObject(source)) {
return source
}
let target = Array.isArray(source) ? [] : {}
for (const key in source) {
if (Object.hasOwnProperty.call(source, key)) {
target[key] = deepClone1(source[key])
}
}
return target
}
JSON方式实现简易深拷贝
JSON.parse( JSON.stringify(obj) )
- 不能拷贝函数、正则、 日期等
完整深拷贝
- 需要考虑函数、正则、日期、set、map、Symbol
- 需要考虑循环引用问题
// 判断是否是引用类型
function isObject(val) {
return val !== null && (typeof val === 'object' || typeof val === 'function')
}
function deepClone(source, map = new WeakMap()) {
// Date类型
if (source instanceof Date) {
return new Date(source)
}
// 正则
if (source instanceof RegExp) {
return new RegExp(source)
}
// source为基本数据类型
// number string boolean null undefined Symbol
if (!isObject(source)) {
return source;
}
// source函数类型
if(typeof source === 'function'){
return source
}
if (map.has(source)) {
return map.get(source)
}
// source为引用类型
const target = Array.isArray(source) ? [] : {};
map.set(source, target)
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = deepClone(source[key], map);
}
}
return target;
}
// 循环引用问题
obj._self = obj
let obj_copy = deepClone(obj)
console.log(obj);
console.log(obj_copy);