对象的深浅拷贝

值类型与引用类型

值类型
简单来说,值类型就是将一个变量赋值给另一个变量后,两个变量完全独立,改变其中的一个并不会影响另一个。

var a = 1;
var b = a; // b = 1
a = 2; // a = 2   b = 1

像上面的例子中,虽然后声明的变量b赋予了a的值,但是改变a的值,b却没有改变

除了数值类型,与此类似的 js 中的值类型还有布尔值、字符串、null、undefined等

引用类型
引用类型刚好与值类型相反,原始的变量被改变后,被赋值的变量也会被改变

引用类型会在内存中开辟一块区域保存它的值,而被赋予了这个值的原始变量本质上是将指向了这块内存,而被赋值的另一个变量获得的也只是这个指向而已

所以一旦内存上的值改变,所有只想这块内存的变量的值都会被改变

var c = [1,2,3];
var d = c; // d = [1,2,3]
c[0] = 0; // c = [0,2,3]   d = [0,2,3]

js 中常见引用类型有 数组、对象、函数

对象的浅拷贝

对象的浅拷贝简单,就是将一个变量赋给另一个变量

var obj1 = {
    name: 'test name',
    age: 18
}

var obj2 = obj1;

上面的例子中 obj2 经过浅拷贝拥有了 obj1 的属性

浅拷贝存在的问题

我们知道引用类型的赋值其实是改变了变量的指向,那么如果在需要拷贝的对象中存在某个属性的值是引用类型,如数组或子对象,那么浅拷贝后的原对象的属性获得的也只是这个指向

所以如果改变被拷贝对象的属性值,那么原对象的相应属性也会跟着改变

对象的深拷贝

深拷贝其实就是将对象中的数组、子对象进行深度递归遍历,直到其不是引用类型位置再进行复制,这样即使改变了其中一个的值,也不会影响到另一个

JSON.parse()与 JSON.stringify()

var target = JSON.parse(JSON.stringify(source2))
target['0'] = 5
target['3'].name = 'anpoly'
target['4'][0] = 6
console.log(source2)  // {0: 1, 1: null, 2: undefined, 3: {name: "anjou", age: undefined, sex: null}, 4: [2, 3, 4], 5: 
ƒ ()}
console.log(target)  // {0: 1, 1: null, 3: {name: "anpoly", sex: null}, 4: [6, 3, 4]}

可以实现对象的深度克隆,但是一些不安全的JSON值(undefined 、 function 和 symbol)无法拷贝。这是因为JSON.stringify(…) 在对象中遇到 undefined 、 function 和 symbol 时会自动将其忽略, 在 数组中则会返回 null (以保证单元位置不变)

克隆函数

深拷贝的缺点

虽然深拷贝能够避免浅拷贝出现的问题,但是却会带来性能上的问题,如果一个对象非常复杂或数据庞大,所消耗的性能将会是很可观的。

// 克隆函数
function deepCopy(data) {
    if (typeof data !== 'object' || data == null) return data
    var newData = data instanceof Array ? [] : {}
    for (var key in data) {
        newData[key] = typeof data[key] === 'object' ? (data[key] === null ? null : deepCopy(data[key])) : data[key]
    }
    return newData
}
var target = deepCopy(source)
target[0] = 5
target[3].name = 'anpoly'
target[4][0] = 6
console.log(source)  // [1, null, undefined, {name: 'anjou', age: undefined, sex: null}, [2, 3, 4], ƒ ()]
console.log(target)  // [5, null, undefined, {name: 'anpoly', age: undefined, sex: null}, [6, 3, 4], ƒ ()]

递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值