js深拷贝与浅拷贝

19 篇文章 0 订阅

区别: 浅拷贝只是增加了一个指针指向已存在的内存地址,仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅拷贝复制出来的对象也会相应的改变。深拷贝是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存。

浅拷贝

一、JavaScript 存储对象都是存地址的,所以浅拷贝会导致 ab 指向同一块内存地址。
数组的复制其实相当于复制了索引,改变其中一个变量,其他引用也会随之改变。

var a = [1,2,3];  
var b = a;  
b[0] = 4;  
// a 为 4 2 3  
// b 为 4 2 3  

var a = [1,2,3];
var b = a;
b[0] = 4;
// a 为 4 2 3
// b 为 4 2 3

当传递一个对象(在 javascript 里数组不是简单数据类型,而是对象)到一个函数,如果在函数内部改变了参数的内容,在函数外部这个变化是可见。

var a = [1,2,3];
function test(a){
  a[0]=4;
  return a;
}
test(a);
// a 为 [4,2,3]

二、Object.assign()方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

案例一:

const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2

案例二:

var person = {
  id: '123',
  name: {
    firstName:'zhang',
    lastName: 'san'
  },
  sex: 'man',
}
var person2 = Object.assign({}, person)
person2.name.lastName = 'qiang'

/* 
person 为 {
  id: '123',
  name: {
    firstName:'zhang',
    lastName: 'qiang'
  },
  sex: 'man',
}

person2 为 {
  id: '123',
  name: {
    firstName:'zhang',
    lastName: 'qiang'
  },
  sex: 'man',
}
*/

上面代码中,源对象 obj1a 属性的值是一个对象,Object.assign() 拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。

深拷贝

slice 函数
concat 函数

这两个函数的原理都是返回数组的一个副本(相当于另外开辟内存空间),所以不会改变数组本身的值。

通常情况下,我们也会采用 JSON.parse(JSON.stingify(obj)) 方法深拷贝。

原理:利用 JSON.stingify 将js 对象序列化(JSON字符串),再使用 JSON.parse 来反序列化(还原)js 对象。但以下几点不适用该方法:

  • 如果 obj里面有时间对象,则 JSON.stringify 后再 JSON.parse 的结果,时间将只是字符串的形式。而不是时间对象;
  • 如果 obj 里有 RegExpError 对象,则序列化的结果将只得到空对象;
  • 如果 obj 里有函数,undefined,则序列化的结果会把函数或 undefined 丢失;
  • 如果 obj 里有 NaNInfinity-Infinity,则序列化的结果会变成 null
  • JSON.stringify() 只能序列化对象的可枚举的自有属性,例如 如果 obj 中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj)) 深拷贝后,会丢弃对象的 constructor
  • 如果对象中存在循环引用的情况也无法正确实现深拷贝;

参考文章

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值