javascript中的浅拷贝和深拷贝(面试高频考点)

深拷贝和浅拷贝的区别是什么?如何实现?

深拷贝和浅拷贝概念
  • 浅拷贝:只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做浅拷贝(浅复制)。浅拷贝只复制指向某个对象的指针(引用地址),而不复制对象本身,新旧对象还是共享同一块内存。
  • 深拷贝: 在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,以保证深拷贝的对象的引用图不包含任何原有对象或对象图上的任何对象,拷贝后的对象与原来的对象是完全隔离,互不影响.

浅拷贝的方法:

  1. 直接赋值
 /** 1. 直接赋值 */
var obj1 = {
    name : 'zhangsan',
    age : 18,
    hobby : {
       fottball : 5
    }
}
var obj2 = obj1;
obj1.name = 'lisi';
obj2.age = 20;
obj2.hobby.fottball = 10;
console.log(obj1); 
console.log(obj2);  

在这里插入图片描述
2.Object.assign 方法

/** 2. Object.assign 方法 */
var obj1 = {
    name : 'zhangsan',
    age : 18,
    hobby : {
       fottball : 5
    }
}
var obj2 = Object.assign({} , obj1);
obj1.age = 20;
obj2.name = 'lisi';
obj2.hobby.fottball = 20;
console.log(obj1);
console.log(obj2);

在这里插入图片描述

  1. 使用 es6 的扩展运算符
 /** 3. ES6的扩展运算符 */
var obj1 = {
    name : 'zhangsan',
    age : 18,
    hobby : {
       fottball : 5
    }
}
var obj2 = {...obj1};
obj1.name = 'lisi';
obj2.age = 20;
obj2.hobby.fottball = 20;
console.log(obj1);
console.log(obj2);

在这里插入图片描述

  1. 数组的 slice 和 concat 方法
    concat:
/** 4.数组的slice 和 concat 方法 */
var arr1 = [1, 3, 'str', {name: 'zhangsan'}];
var arr2 = arr1.concat();
arr1[0] = 2;
arr2[2] = 'arr';
arr2[3].name = 'lisi';
console.log(arr1);
console.log(arr2);

在这里插入图片描述

slice:

var arr1 = [1, 3, 'str', {name: 'zhangsan'}];
var arr2 = arr1.slice();
arr1[0] = 2;
arr2[2] = 'arr';
arr2[3].name = 'lisi';
console.log(arr1);
console.log(arr2);

在这里插入图片描述

  1. jquery 中的 extend 方法
 /** 5.jquery 的 extend 函数
 * $.extend() 里面有三个参数,第一个参数 true 为深拷贝,false为浅拷贝, 第二个参数是要拷贝的对象,第三是被拷贝的对象
 * 第一个参数默认是 false ,即默认是浅拷贝
 */
var obj1 = {
    name : 'zhangsan',
    age : 18,
    hobby : {
       fottball : 5
    }
}
var obj2 = {};
$.extend(obj2 , obj1);
obj2.age = 20;
obj2.hobby.fottball = 20;
console.log(obj1);
console.log(obj2);

在这里插入图片描述

深拷贝的方法:
1.JSON.parse(JSON.stringify())

var obj1 = {
    name : 'zhangsan',
    age : 18,
    hobby : {
       fottball : 5
    }
}
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.age = 20;
obj2.hobby.fottball = 20;
console.log(obj1);
console.log(obj2);

在这里插入图片描述

但是这种方法有缺陷,JSON.parse 和 JSON.stringify 原本是处理 JSON对象的,JSON对象没有函数类型,因此若对象里面有函数,用该方法会丢失函数,如下所示:

var obj1 = {
    name : 'zhangsan',
    age : 18,
    hobby : {
       fottball : 5
    },
    sayHi : ()=>{
        console.log(this.name)
    }
}
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.age = 20;
obj2.hobby.fottball = 20;
console.log(obj1);
console.log(obj2);

在这里插入图片描述

  1. 使用 jquery 的 extend 方法
/**  深拷贝 2.jquery 的 extend 函数
 * $.extend() 里面有三个参数,第一个参数 true 为深拷贝,false为浅拷贝, 第二个参数是要拷贝的对象,第三是被拷贝的对象
 * 第一个参数默认是 false ,即默认是浅拷贝
 */
var obj1 = {
    name : 'zhangsan',
    age : 18,
    hobby : {
       fottball : 5
    }
}
var obj2 = {};
$.extend(true , obj2 , obj1);
obj2.age = 20;
obj2.hobby.fottball = 20;
console.log(obj1);
console.log(obj2);

在这里插入图片描述
3.手写深度拷贝递归函数

var obj1 = {
    name : 'zhangsan',
    age : 18,
    hobby : {
       fottball : 5
    }
}
function deepClone(target){
    var result; // result : 要返回的深度克隆后的对象
    if(typeof target === 'object'){
        if(Array.isArray(target)){
            // target 对象是数组
            result = [];
            for(let i in target){
                result.push(deepClone(target[i]));
            }
        }else if(target === null){
            // target 为 null , 值为 null 的变量 typeof 也为 object
            result = null;
        }else if(target.constructor === RegExp || target.constructor === Date){
            //target 为正则表达或Date , 这两种的 typeof 也为 object
            result = target;
        }else{
            //进入该分支,表明target 是一个对象
            result = {};
            for(let i in target){
                result[i] = deepClone(target[i]);
            }
        }
        return result;
    }else{
        // 进入此分支,代表 target 是 number ,string ,booblean 一类的原始值,因此直接赋值就可
        result = target;
        return result;
    }
}
var obj2 = deepClone(obj1);
obj2.age = 20;
obj2.hobby.fottball = 20;
console.log(obj1);
console.log(obj2);

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值