(只谈论了 基本数据类型 和 ES5 的引用数据类型)
(关于 ES6 及之后 新增的Symbol,Map 等数据类型还有待谈论)
(以下仅为 原生JS 的方法,未涉及第三方库使用,第三方库lodash也有函数可实现)
最外部一层所有的层级对于下面这个 对象
const hotGirl = {
name: 'Maji',
age: 28,
info: {
desc: 'superHot',
},
};
name和age拥有新地址,但是 拷贝到 info时 则会引用原始对象 中的地址info.desc的值时,浅拷贝出来的新对象的info.desc的值同样会改变),不彻底拷贝,所以 只有一层属性的对象 适合浅拷贝。彻底的拷贝只拷贝最外面一层的数据-(不彻底的拷贝)Object.assign(target,source01,source02,...)语法:(将source对象中的值 拷贝到 target目标对象中)
target 可以写成空对象
**注意:**若target非空 ,且source 和 target中有重复属性 ,则target中的属性会被覆写;target的值会被改变, 但是source的值不会
// obj2 拿到的就是 target
let obj2 = Object.assign(target,source)
const hotGirl = {
name: 'Maji',
age: 28,
};
// target `可以写成空对象`
let newHotGirl = Object.assign({},hotGirl)
console.log(newHotGirl)
// {name: 'Maji', age: 28}

const hotGirl = {
name: 'Maji',
age: 28,
};
const pureGirl = {
name: 'Olla',
age: 26,
tall:"180cm"
};
// 让Olla 从 pureGirl 成为 hotGirl
// 注意这里 hotGirl 的属性被改变了,pureGirl没有
Object.assign(hotGirl,pureGirl)
// target `可以写成空对象`
console.log(hotGirl)
// {name: 'Olla', age: 26, tall: '180cm'}

(...)const hotGirl = {
name: 'Maji',
age: 28,
};
let newHotGirl = { ...hotGirl }
console.log(newHotGirl)
//{name: 'Maji', age: 28}
const hotGirl = {
name: 'Maji',
age: 28,
};
const newHotGirl = {};
// 用 for in 将 obj1 的值拷贝给 obj2
for (let key in hotGirl) {
//字符串 赋值 就是开辟 新的内存地址,成为完全的新值
newHotGirl[key] = hotGirl[key];
}
console.log(newHotGirl)
//{name: 'Maji', age: 28}
每一层数据都会拷贝-(最彻底的拷贝)let newObj = JSON.parse(JSON.stringify(obj))
undefinedsymbolJSON.stringify() 会默认移除函数。JSON.stringify() 无法拷贝 Map、Set、RegExp 这些特殊数据类型。structuredClone[MDN—structuredClone()](structuredClone() - Web 开发技术 | MDN (mozilla.org))
结构化拷贝算法的实现,能够实现几乎对所有数据类型的深拷贝
该API 较新,兼容要考虑(目前主流都支持) ,虽然有些缺点,但是不影响,放心用,以后应该会加大支持力度
core-js 兼容库 core-js#structuredclone,兼容旧版本。相比 JSON.parse() ,structuredClone API 的性能更好
语法:
let hotGirl = {
age: 1,
info: {
cup: 'E'
}
}
let newHotGirl = structuredClone(hotGirl);
console.log(newHotGirl)
原型:无法拷贝对象的原型链。
函数:无法拷贝函数。(普通函数、箭头函数、类、方法)
let hotGirl = {
age: 1,
info: {
cup: 'E'
},
f:function(){
console.log('hot')
}
}
let newHotGirl = structuredClone(hotGirl);
console.log(newHotGirl)

DOM节点
不可克隆:并没有支持所有类型的拷贝,比如 Error。
完整源码
// 手写深拷贝
export function deepClone(obj) {
//判断 传入对象 为 数组 或者 对象
var result = Array.isArray(obj) ? [] : {};
// for in 遍历
for (var key in obj) {
// 判断 是否 为自身 的属性值(排除原型链干扰)
if (obj.hasOwnProperty(key)) {
// 判断 对象的属性值 中 存储的 数据类型 是否为对象
if (typeof obj[key] === 'object') {
// 有可能等于 null
if (obj[key] === null ) {
result[key] = null
continue
}
// 递归调用
result[key] = deepClone(obj[key]); //递归复制
}
// 不是的话 直接 赋值 copy
else {
result[key] = obj[key];
}
}
}
// 返回 新的对象
return result;
}
补充说明
if (typeof obj[key] === 'object')' 之内增加判断null 操作;修复之前(将null 拷贝成 {}的问题)if (typeof obj[key] === 'object') {
// 有可能等于 null
if (obj[key] === null ) {
result[key] = null
continue
}
// 递归调用
result[key] = deepClone(obj[key]); //递归复制
}