(在探讨深浅拷贝前,我们先来看看js数据类型)
一、js数据类型
1、javaScritp的数据类型有:数值类型、字符串类型、布尔类型、null、undefined、对象;将他们可以大致分成两种:**基本数据类型和引用数据类型**;
(1)、基本数据类型:数值、字符串、布尔、null、undefined (值类型)
(2)、复杂(复合)数据类型:对象 (引用类型)
**基础数据类型保存在栈内存中,引用类型保存在堆内存中,但是对象的引用内存地址是存储在栈内存中的;我们调用基础数据类型是直接调用值,而我们操作对象实际上是通过调用其引用内存地址来操作的**
2、基础数据类型与引用数据类型的拷贝
(1)、基础数据类型的拷贝
var a = 1;
var b = a;
console.log(a); // 1
console.log(b); // 1
(2)、引用数据类型的拷贝
var obj1 = ['width', 'height']
var obj2 = obj1;
//给obj2新增一个元素
obj2.push('color');
console.log(obj1);
console.log(obj2);
为什么我们给obj2新增一个color的元素,obj1也有这个元素呢?
*原因在于,我们把obj1赋值给obj2,赋值给obj2的只是obj1的引用内存地址,所以他们两个的数据的堆内存其实是同一个;当我们改变obj2元素时,实际也是改变了obj1。*所以简单的复制对引用数据类型是没有作用的!
总结:由此我们可以延伸出我们今天的主题:深浅拷贝!
二、深浅拷贝
**1、浅拷贝就如果我上面讲解的例子一样;**
如果是基础数据类型,浅拷贝只是拷贝其数据;如果是引用数据类型,我们只是拷贝的引用内存地址,共用一个堆内存,并不是一个新的对象;故而存在一个问题,一个对象数据改变,另一个也跟着变:
**2、深拷贝**
深拷贝就是创造出一个新对象,不共用内存,修改数据,不会影响原对象!
var arr = [1, 2, 3, 4];
var newArr = [];
// 用forEach循环遍历的方法,将原对象数据添加到新对象中
arr.forEach(function (item) {
newArr.push(item);
})
// 修改新对象数据
newArr[0] = 9;
console.log(arr);
console.log(newArr);
(对新数组数据修改后,并没有影响原来数组,这就是深拷贝!)
总结:如何区分深拷贝与浅拷贝?
简单点来说,如果B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短;如果B没变,那就是深拷贝,坚守本心;