js的栈堆与浅拷贝、深拷贝的理解

一:什么是堆栈?

  我们都知道:在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(top))对数据项进行插入和删除。

  • 堆:队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  • 栈:先进后出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。 
    以上都属于计算机基础部分,在此都不详细赘述了,下面我们联系JavaScript来剖析一下堆栈。
  • 栈堆之间的关系,在栈中存放的基本类型数据如果包含了应用类型(heap),那么栈中存放的只是堆中的一个地址,根据这个地址系统可以找到数据在堆中的位置。

二:JavaScript中的基本类型和引用类型与堆栈有什么联系?

JavaScript的数据类型分为两大种: 
1. 基本类型:Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。 
2. 引用类型:Object,Array,Date,RegExp,Function 即存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。 
  以上我们知道了什么是堆栈,和JavaScript的数据类型,下面我们根据js的数据类型来说明一下他们的拷贝情况:

结合下面的例子理解堆栈的关系:

	var xm = {
		age: 18,
		score: 4
	};
	var xh = {
		age: 18,
		score: 4
	};
	console.log(xm===xh);   //false

var  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

其他的方法需要使用递归操作来进行。

方法二:

  function deepCopy(obj) {                                 
            var str,newObj=obj.constructor===Array?[]:{};
            if (typeof(obj)!=='object'){
                return obj
            }else if(window.JSON){
                str= JSON.stringify(obj);
                newObj=JSON.parse(str)
            }else{
                for(let i in obj){
                    newObj[i]=typeof(obj[i])=='object'?deepCopy(obj):obj[i] 
                }
            }
            return newObj
        }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值