小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
主要介绍了数组和对象的浅拷贝和深拷贝,实现方式有 slice(), concat(), Array.from, 扩展运算符,Object.assign(), JSON.stringify(), 循环递归拷贝等等
浅拷贝:共用一个内存地址,只复制了指针,变化会互相影响
深拷贝:创建一个全新的对象,不共享内存,改变不会互相影响
数组
深拷贝
slice()
concat()
Array.from
Array.from("foo"); // 从string生成数组
const set = new Set(["foo", "bar", "baz", "foo"]);
Array.from(set); // 从 Set 生成数组
const map = new Map([
[1, 2],
[2, 4],
[4, 8],
]);
Array.from(map); // 从 Map 生成数组
function f() {
return Array.from(arguments); // 从类数组对象(arguments)生成数组
}
f(1, 2, 3);
- 扩展运算符
// 数组拷贝
let arr = [1, 2, 3];
let arrCopy = [...arr];
// 对象拷贝
let obj = {
a: "a",
b: "b",
};
let objCopy = { ...obj };
// 数组合并 可代替concat
let newArr = [...arr1, ...arr2];
// 函数形参
func(1, 2, 3);
func(...rest); // 1 2 3
func(first, ...rest); // 1; 2 3
// 字符串转数组
let newArr = [...str];
对象
浅拷贝
Object.assign()
:对于简单类型和只有一层数据的对象是深拷贝,对于嵌套对象和引用类型是浅拷贝
深拷贝
- 序列化:JSON.parse(JSON.stringify(obj))
- 有限制,
undefined
、symbol
和函数
及其他特殊格式
没法实现
- 有限制,
- 手写循环递归
function deepClone(obj, hash = new WeakMap()) {
// 处理null或者undefined
if (obj === null) return obj;
// 处理日期类型
if (obj instanceof Date) return new Date(obj);
// 处理正则类型
if (obj instanceof RegExp) return new RegExp(obj);
// 普通值或函数不需要深拷贝
if (typeof obj !== "object") return obj;
// 对象进行深拷贝
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
参考文档: