Javascript中的深拷贝和浅拷贝

关于Javascript中的深拷贝和浅拷贝

Javascript中的深拷贝和浅拷贝最根本的区别在于是否真正获取了实体对象的复制实体

例如:B复制了A
浅拷贝:修改A时,B也会跟着发生变化(指针还是指向A)
深拷贝:修改A时,B不会发生变化(已经拿到A的实体,你改任你改)

区别

浅拷贝:只是增加一个指针指向已存在的内存地址,原地址发生改变,浅拷贝出的对象也会发生改变
深拷贝:增加了一个指针并开辟了新的内存,指向新的内存地址

浅拷贝容易出现释放内存时释放了同一个内存的错误,深拷贝就不会

浅拷贝实现方法

(1)直接赋值:

var obj1={
    a:1,
    b:2
}
var obj2=obj1;
console.log(obj2);

输出:
浅拷贝
此时改变原值:

obj1.a=3;
console.log(obj1);
console.log(obj2);

输出:
浅拷贝
(2)for…in循环

function simpleCopy(obj1) {
   var obj2 = Array.isArray(obj1) ? [] : {};
   for (let i in obj1) {
   obj2[i] = obj1[i];
  }
   return obj2;
}
var obj1 = {
   a: 1,
   b: 2,
   c: {
         d: 3
      }
}
var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
alert(obj1.a); // 1
alert(obj2.a); // 3
alert(obj1.c.d); // 4
alert(obj2.c.d); // 4

(3)Object.assign方法:

var obj = {
    a: 1,
    b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3

深拷贝实现方法

(1)递归:

function deepClone(obj){
    let objClone = Array.isArray(obj)?[]:{};
    if(obj && typeof obj==="object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                //判断ojb子元素是否为对象,如果是,递归复制
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}    
let a=[1,2,3,4],
    b=deepClone(a);
a[0]=2;
console.log(a,b);

输出:
深拷贝

(2) 通过JSON对象来实现:

function deepClone2(obj) {
  var _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
  return objClone;
}

该方法的缺点:无法深拷贝对象中的方法,会显示undefined

(3)通过jQuery的extend方法:

var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝

(4)手动实现深拷贝:

let obj1 = {
   a: 1,
   b: 2
}
let obj2 = {
   a: obj1.a,
   b: obj1.b
}
obj2.a = 3;
alert(obj1.a); // 1
alert(obj2.a); // 3

(5)slice实现对数组的深拷贝:

var arr1 = ["1","2","3"]; 
var arr2 = arr1.slice(0);
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );

当数组里面的值是基本数据类型,比如String,Number,Boolean时,属于深拷贝
当数组里面的值是引用数据类型,比如Object,Array时,属于浅拷贝

(6)concat实现对数组的深拷贝

var arr1 = ["1","2","3"];
var arr2 = arr1.concat();
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );

var arr1 = [{a:1},{b:2},{c:3}];
var arr2 = arr1.concat();
arr2[0].a = "9";
console.log("数组的原始值:" + arr1[0].a ); // 数组的原始值:9
console.log("数组的新值:" + arr2[0].a ); // 数组的新值:9

(7)var newObj = Object.create(oldObj):

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];  // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值