一:什么是堆栈?
我们都知道:在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(top))对数据项进行插入和删除。
- 堆:队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
- 栈:先进后出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。 以上都属于计算机基础部分,在此都不详细赘述了,下面我们联系JavaScript来剖析一下堆栈。
- 栈堆之间的关系,在栈中存放的基本类型数据如果包含了应用类型(heap),那么栈中存放的只是堆中的一个地址,根据这个地址系统可以找到数据在堆中的位置。
二:JavaScript中的基本类型和引用类型与堆栈有什么联系?
JavaScript的数据类型分为两大种:
1. 基本类型:Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。 2. 引用类型:即存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。 以上我们知道了什么是堆栈,和JavaScript的数据类型,下面我们根据js的数据类型来说明一下他们的拷贝情况:结合下面的例子理解堆栈的关系:
var xm = { age: 18, score: 4 }; var xh = { age: 18, score: 4 }; console.log(xm===xh); //falsevar newobj=xh console.log(newobj===xh); //true//下面这也是一个你叫经典的例子可以试一下 function setName(obj) { obj.name = 'xm'; //在传参数中新建内存对象,并且设定一个值 obj = {}; //对象是引用类型。系统在堆中新建一个内存空间,与传入值无关。 obj.name = 'xh'; //在新建的内存空间设置一个值(与传入值是独立开来的。) } var person = {}; setName(person); console.log(person.name); // xm//console.log([] instanceof Array);// console.log(typeof []);
xm和xh的对象值是一样的,可是在关系比较重为false,当新建对象赋值是这种情况就是true.下图给大家讲解。
这就会出现另外一种情况,我们想去判断引用类型的值是否相等,(下面以对象为例子进行讲解。)
var xm = { age: 18, score: 4 }; var xh = { age: 18, score: 4 };function equalObjs(a, b) { for (var p in a) { if (a[p] !== b[p]) return false; } return true; }
三:什么是浅拷贝?
基本类型拷贝的时候只是在内存中又开辟了新的空间,是的新建的值与拷贝值相互独立。(可以理解为在堆中新建一个空间存放同样的值。)这个方法可以利用上面判断相等的办法遍历出堆(heap)值重新赋值。因此深浅拷贝是相对于引用类型的。
var xm = { age: 18, score: 4, arr1:[1,32] }; function copyObj(obj) { var newObj = {}; for (var p in obj) { newObj[p] = obj[p]; } return newObj; } var xh = copyObj(xm); // var arr1=[1,2,3] xh.arr1.push(33) console.log(xh) //{age: 18, score: 4, arr1: Array(3)} console.log(xh===xm); //false console.log(xh.arr1===xm.arr1); //true
console.log(xh.arr1===xm.arr1); //true 这里出现了一个问题,浅拷贝中遍历对象里面包含了另外一个应用类型(arr1),而它的空间是独立的,这样直接被引用。
如果想实现两个值的完全独立,这时就需要使用到深拷贝。
四:深度拷贝
根据浅拷贝出现的问题,我们可以使用深拷贝的方法解决问题。
深拷贝的方法比较多,我举一些比较简单的例子来说明一下。
最简单的办法:JSON.parse(obj)
var xm = { age: 18, score: 4, arr1:[1,32] }; var xh=JSON.parse(JSON.stringify(xm)) xh.arr1.push(33) console.log(xh) //{age: 18, score: 4, arr1: Array(3)} console.log(xh===xm); //false console.log(xh.arr1===xm.arr1); //false
其他的方法需要使用递归操作来进行。