一:什么是堆栈?
我们都知道:在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(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=xhconsole.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); //falseconsole.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); //falseconsole.log(xh.arr1===xm.arr1); //false
其他的方法需要使用递归操作来进行。