JavaScript内存及浅拷贝和深拷贝

拷贝,理解为复制的意思,拷贝就是复制已经存在的一个变量给另外一个变量,如:var a = 10; var b = a; b拷贝了a。那么 a 等不等于 b 呢?要搞明白我们得先来了解下JavaScript的内存管理机制。

JavaScript的内存管理机制

内存的周期是: 分配 -> 使用 -> 释放

1. 分配:

变量被定义时候分配内存,内存存放又分为栈、堆、地址池。其中存放变量,且有固定的大小(基础数据),存放复杂对象(引用数据类型),存放常量。

注意:JS不允许直接访问堆内存中的位置,因此我们不能直接操作对象的堆内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,引用类型的值都是按引用访问的。这里的引用,我们可以粗浅地理解为保存在栈内存中的一个地址,该地址与堆内存的实际值相关联。


2. 使用:

对分配内存进行读取与写入的操作。如: var a = 1;a = 2; // 写入内存

3. 释放:

所分配的内存确实已经不再需要了,释放这过程涉及了垃圾回收机制,Javascript内嵌了垃圾收集器,用来跟踪内存的分配和使用,以便当分配的内存不再使用时,自动释放它(如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收)。垃圾收集器会按照固定的时间间隔,或代码执行中预定的收集时间,周期性地执行这一操作。如下:

function fun1(){ var obj = {name:'ja'};}  var f1 = fun1(); obj 会被回收,因为var obj使用完

function fun2(){var obj = {name:'va'};return obj;}var f2 = fun2(); obj 不会被回收,因为被f2引用,f2属于全局变量,页面没有卸载的情况下是不会被回收的



JavaScript的浅拷贝和深拷贝

基本数据类型不存在浅深拷贝问题,引用类型存在

1. 浅拷贝:浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改对象,原对象也会改变。方法:Object.assign()(当object只有一层的时候,是深拷贝)、Array.prototype.concat()Array.prototype.slice()

2. 深拷贝:深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象方法:JSON.parse(JSON.stringify())(但不能处理函数、underfined)、遍历对象(只有一层对象直接循环,两层对象则需要判断类型)、递归(多层对象)


浅拷贝:

深拷贝:


一层对象深拷贝


两层对象深拷贝


递归拷贝:

var p = { "id":"007","name":"刘德华","wife":{"id":"008","name":"刘德的妻子","address":{"city":"北京","area":"海淀区"}}}

//写函数

function copyObj(obj){let newObj={};for(let key in obj){if(typeof obj[key] =='object'){//如:key是wife,引用类型,那就递归newObj[key] = copyObj(obj[key])}else{//基本类型,直接赋值newObj[key] = obj[key];}}return newObj;}

let pNew = copyObj(p);pNew.wife.name="张三疯";pNew.wife.address.city = "香港";console.log(pNew);console.log(p);

你可能感兴趣的:(JavaScript内存及浅拷贝和深拷贝)