深拷贝和浅拷贝
说起深拷贝和浅拷贝,首先我们来看两个栗子
// 栗子1
var a = 1,b=a;
console.log(a);
console.log(b)
b = 2;
console.log(a);
console.log(b)
// 栗子2
var obj1 = {x: 1, y: 2}, obj2 = obj1;
console.log(obj1) //{x: 1, y: 2}
console.log(obj2) //{x: 1, y: 2}
obj2.x = 2; //修改obj2.x
console.log(obj1) //{x: 2, y: 2}
console.log(obj2) //{x: 2, y: 2}
按照惯性思维,栗子1中obj1应该跟a一样,不会因另外一个值的改变而改变的啊,而这里却是obj1跟着obj2的改变而改变了?同样都是变量,怎么就表现不一样了呢?难道存在等级上的优劣?此处需要沉思一小会。要解决这个问题,就要引入一个JS中基本类型和引用类型的概念了。
基本类型和引用类型
ECMAScript变量包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。而引用类型值是指那些保存堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象。
两类数据的保存方式
从上图可以看到,栈内存主要用于存储各种基本类型的变量,包括Boolean、Number、String、Undefined、Null等以及对象变量的指针。而堆内存主要负责对象Object这种变量类型的存储。目前基本类型有:
Boolean、Null、Undefined、Number、String、Symbol,引用类型有:Object、Array、Function。Symbol就是ES6才出来的,之后也可能会有新的类型出来。
让我们再回到前面的案例,栗子1中的值为基本类型,栗子2中的值为引用类型,栗子2中的赋值就是典型的浅拷贝。我们需要明确一点,深拷贝与浅拷贝的概念只存在于引用类型。
既然已经知道了深拷贝与浅拷贝的来由,那么该如何实现深拷贝?我们分别来看看Array和Object自有方法是否支持:
var arr1 = [1, 2