本篇文章将整理一下深浅拷贝的相关知识。文章包括以下内容:
- 基本类型和引用类型
- 对象的深拷贝和浅拷贝
基本类型和引用类型
JS中包含两种数据类型,既基本类型和引用类型,基本类型是简单的数据段,它是按值访问的,因为基本类型可以操作保存在变量中的值。而引用类型指的是那些可能由多个值构成的对象。引用类型的值是保存在内存中的对象,在JS中,规定不能直接访问内存中的位置,既不能直接访问内存中的变量。所以在访问引用类型时实际上是按引用访问的。
那么在复制基本类型和引用类型时存在着怎样的不同呢?当从一个变量向另一个变量复制基本类型值时,会在变量对象上创建一个新值,然后把改值复制到新变量分配的位置上。基本类型值复制实际上是生成了一个新的副本,它们参与的操作不会相互收到影响。
var num1 = 10;
var num2 = num1;
console.log(num2); // 10;
num2 = 20;
console.log(num2); // 20;
console.log(num1); // 10;
//num2由num1复制而来,但是改变num2时,原来的num1并不会受到影响。
当从一个变量向另一个变量复制引用类型时,同样会将存储的对象复制一份到新的变量中。不同的是,这个值得副本实际上是一个指针,指针指向存储中的对象。两个变量引用的是同一个对象。因此改变其中一个变量的值,将影响另一个变量的值。
var obj1 = {
name: 'hyt'
}
var obj2 = obj1;
obj2.name = 'newHyt';
console.log(obj1.name); // newHyt;
对象的深拷贝和浅拷贝
1、浅拷贝
当复制一个数组/对象时,只是复制了数组/对象的引用,改变数组/对象中的值,另一个数组/对象也会跟着改变,这往往不是我们想要的。
function simpleClone(obj) {
let newObj = {};
for (let k in obj) {
newObj[k] = obj[k];
return newObj;
}
}
var obj1 = {a: {b: {c: 1}}};
var obj2 = simpleClone(obj1);
console.log(obj2);
obj2.a.b.c = 'hyt';
obj1.a.b.c = 'hyt';
2、深拷贝
目标是拷贝一个对象时,更改一个变量,另一个变量不受影响。在这里将介绍三种方式实现对象的深拷贝。
对象的深拷贝实现原理: 定义一个新的对象,遍历源对象的属性并赋给新对象的属性
- 递归实现深拷贝
- es6的扩展运算符
递归—就是对每一层的数据都实现一次 创建对象->对象赋值 的操作,简单粗暴上代码:
function deepClone(source){
const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
for(let keys in source){ // 遍历目标
if(source.hasOwnProperty(keys)){
if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
targetObj[keys] = source[keys].constructor === Array ? [] : {};
targetObj[keys] = deepClone(source[keys]);
}else{ // 如果不是,就直接赋值
targetObj[keys] = source[keys];
}
}
}
return targetObj;
}
es6的扩展运算符
var obj = {
name: 'FungLeo',
sex: 'man',
old: '18'
}
var { ...obj2 } = obj
obj.old = '22'
console.log(obj) ///{ name: 'FungLeo', sex: 'man', old: '22'}
console.log(obj2) ///{ name: 'FungLeo', sex: 'man', old: '18'}