js深拷贝浅拷贝

对数据进行备份是一个常见的问题。那么什么是深拷贝浅拷贝呢?
我们都知道js的数据类型有值类型和引用类型。

  • 值类型:通过赋值即可实现数据备份
  • 引用类型:由于变量中保存的只是指向数据值的指针,因而若简单复制变量,那么若改变变量,原对象也会跟着改变,这就是浅拷贝。所以深拷贝指的自然就是另外开辟一块内存保存对象的值,这样即使改变了拷贝后的数据,原数据也不会改变。

浅拷贝

普通赋值
function clone(copyObj) {
  var obj = {};
  for ( var i in copyObj) {
    obj[i] = copyObj[i];
  }
  return obj;
}
var x = {
  a: 1,
  b: { f: { g: 1 } },
  c: [ 1, 2, 3 ]
};
var y = clone(x);
y.c.push(4);
console.log(x.c); // 1,2,3,4
console.log(y.b.f === x.b.f);     // true

通过改变y的属性值,x的属性值也会相应改变。

ES6 中Object.assign()

用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。该方法是一个浅拷贝方法。

var x = {
  a: 1,
  b: { f: { g: 1 } },
  c: [ 1, 2, 3 ]
};
var y = Object.assign({}, x);
console.log(y.b.f === x.b.f);     // true
Array中的slice和concat方法

slice和concat虽然都是会返回一个新数组,但是它们也是浅拷贝。对于数组中属性值为引用类型的属性只是复制了指针。

let array = [1, [1,2,3], {name:"array"}];
let array_shallow = array;
let array_concat = array.concat();
let array_slice = array.slice(0);

console.log(array === array_shallow); //true
console.log(array === array_slice); //false
console.log(array === array_concat); //false
array_concat[1][0] = 5;
console.log(array[1]); //[5,2,3]
console.log(array_slice[1]); //[5,2,3]
array_slice[2].name = "array_slice";
console.log(array[2].name); //array_slice
console.log(array_concat[2].name); //array_slice

由例子可知,对于引用类型,若是改变拷贝后的值,原值也会被改变。
另外再添加一个小知识点:slice的参数可以是负数,若是负数,则用数组长度加上该数来确定相应的位置。若结束位置小于起始位置,不会报错,而是返回空数组。

深拷贝

JSON

JSON对象的parse方法可以将JSON字符串反序列化成对象,stringify方法可以将对象序列化成JSON字符串。

let source = {
    name:"source",
    child:{
        name:"child"
    },
    fun: function () {
        console.log('function');
    },
    reg: new RegExp("e")
};
let target = JSON.parse(JSON.stringify(source));

console.log(target); //Object {name: "source", child: Object, reg: Object}
console.log(target.fun); // undefined
console.log(target.reg); // Object {}

target.name = "target";  //改变target的name属性
console.log(source.name); //source
console.log(target.name); //target

target.child.name = "target child"; //改变target的child
console.log(source.child.name); //child
console.log(target.child.name); //target child

由例子可知,对于简单的对象使用JSON方法可以实现深拷贝。
但是它还有很多缺点:

  • 对于正则表达式、函数等无法进行深拷贝
  • 这样做的深拷贝会抛弃对象的constructor。
    不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
  • 当遇到层级较深,且序列化对象不完全符合JSON格式时,使用JSON的方式进行深拷贝就会出现问题。
使用递归

。。。。。持续更新中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值