浅拷贝
代码示例-1 直接赋值
let obj = {
name: 'mary',
age: 12,
parents: {
father: 'a',
mother: 'b',
}
}
let obj2 = obj;
obj2.age = 13;
console.log(obj, obj2);
// {name: 'mary', age: 13, parents: {father: 'a', mother: 'b'} {name: 'mary', age: 13, parents: {father: 'a', mother: 'b'}
obj2.parents.father = 'c';
console.log(obj, obj2);
// {name: 'mary', age: 13, parents: {father: 'c', mother: 'b'} {name: 'mary', age: 13, parents: {father: 'c', mother: 'b'}
复制代码
如上代码所示 这是一种直接赋值的方式 两个指向的都是同一块地址 这样会导致 当 其中任意一个对象改变了其里面的属性的时候 则另外一个对象也会发生改变
代码示例-2 浅拷贝的API方式
- Object.assign()
针对对象
- 扩展运算符 concat() slice()
这三个都是针对数组类型的
let obj = {
name: 'mary',
age: 12,
parents: {
father: 'a',
mother: 'b',
}
}
let obj2 = Object.assign({}, obj);
obj2.age = 13;
console.log(obj, obj2);
// {name: 'mary', age: 12, parents: {father: 'a', mother: 'b'} {name: 'mary', age: 13, parents: {father: 'a', mother: 'b'}
obj2.parents.father = 'c';
console.log(obj, obj2);
// {name: 'mary', age: 12, parents: {father: 'c', mother: 'b'} {name: 'mary', age: 13, parents: {father: 'c', mother: 'b'}
let arr1 = [1, 2, 3, { name: 'jack' }];
let arr2 = arr1.concat();
let arr3 = [... arr1];
let arr4 = arr1.slice();
复制代码
可以看到 如果是浅拷贝的方式 那么obj obj2指向的就不是同一个引用的地址 但是限制在于只能拷贝第一层 也就是说当对象里面再去嵌套对象的时候 那么 里面的对象引用的还是同一个地址 如上面的parent 当obj2去改变里面的数据的时候 也会导致obj里面的parent的数据发生改变
代码示例-3 浅拷贝的手动实现
function 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;
}
}
复制代码
深拷贝
深拷贝的API方式
代码示例
let obj = {
name: 'mary',
age: 12,
parents: {
father: 'a',
mother: 'b',
}
}
let obj2 = JSON.parse(JSON.stringify(obj));
obj2.age = 13;
console.log(obj, obj2);
// {name: 'mary', age: 12, parents: {father: 'a', mother: 'b'}
// {name: 'mary', age: 13, parents: {father: 'a', mother: 'b'}
obj2.parents.father = 'c';
console.log(obj, obj2);
// {name: 'mary', age: 12, parents: {father: 'a', mother: 'b'}
// {name: 'mary', age: 13, parents: {father: 'c', mother: 'b'}
复制代码
可以看到深拷贝的方式解决了上面浅拷贝的的问题 可以进行深层次的拷贝
深拷贝的手写实现-1
function deepClone(target) {
if(typeof target === "object" && target !== null){
let cloneTarget = Array.isArray(target) ? [] : {};
for(let prop in target){
if(target.hasOwnProperty(prop)){
cloneTarget[prop] = deepClone(target[prop]);
}
}
return cloneTarget;
}else{
return target;
}
}
复制代码
深拷贝手动实现-2 解决循环引用的问题
let obj = {
name: 'mary',
age: 12,
parents: {
father: 'a',
mother: 'b',
},
};
obj.same = obj;
复制代码
这样 就是一个循环引用的例子 会导致一直拷贝 最终爆内存
思路在于 可以创建一个 map 记录下已经拷贝的对象 如果这个对象已经被拷贝过 则直接返回就好了
function deepClone(target, map = new Map()) {
if(map.get(target)){
return target;
}
if(typeof target === "object" && target !== null){
map.set(target, true);
let cloneTarget = Array.isArray(target) ? [] : {};
for(let prop in target){
if(target.hasOwnProperty(prop)){
cloneTarget[prop] = deepClone(target[prop], map);
}
}
return cloneTarget;
}else{
return target;
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END