js深浅拷贝与内存机制

参考与:js中的栈、堆、队列、内存空间

1、深浅拷贝

将一个变量的值赋值给另一个变量,相当于在栈内存中创建了一个新的内存空间,然后从栈中复制值,存储到这个新空间中。对于基本类型,栈中存储的就是它自身的值,所以新内存空间存储的也是一个值。直接改变新变量的值,不会影响到旧变量的值,因为他们值存储的内存空间不同。

// 基本类型复制变量
let a = 10
let b = a
b = 20
console.log(a,b)//10 20

而对于引用类型来说,同样是复制栈中存储的值。但是栈存储的只是其引用地址,其具体的值存储在堆中。变量复制仅复制栈中存储的引用,不会复制堆中存储的值,所以新变量在栈中的值是一个地址指针。

// 引用类型复制变量
let a = [1,2]
let b = a	//此时a b指向同一堆内存
b.push(5)
console.log(a,b)//[1,2,5] [1,2,5]
console.log(a == b)//true

可见,变量复制赋值,都属于栈存储拷贝,因此深浅拷贝可以这样区分:

  • 浅拷贝:栈存储拷贝
  • 深拷贝:栈、堆存储拷贝

深拷贝会同时开辟新的栈内存,堆内存空间。
目前实现深拷贝的方法不多,主要是两种:
①利用 JSON 对象中的 parse 和 stringify
②利用递归来实现每一层都重新创建对象并赋值(详见下面俩个链接)

// 利用JSON对象方法实现深拷贝
let a = [1,2]
let b = JSON.parse(JSON.stringify(a))
b.push(5)
console.log(a,b)//[1,2] [1,2,5]
console.log(a == b)//false

此方法只能适用于一些简单的情况,像如果要拷贝的对象中有function则不行,undefined、
function、symbol 会在转换过程中被忽略...	如下:

let obj = {
	n:2,
	f:function(){
		console.log(1)
	}
}
let x = JSON.parse(JSON.stringify(obj))
console.log(obj,x)//{n: 2, f: ƒ()} {n: 2}
console.log(obj == x)//false

函数传参是按值传递还是按引用传递?

let person = {age: 17}
function foo(person){
	person.age = 23
}
foo(person)
console.log(person.age)

函数调用时,会对参数赋值。而参数传递过程其实同样是变量复制的过程,所以它是按值传递。var person = person,因为传递参数是对象时,变量复制仅复制的栈存储(浅拷贝),所以修改对象属性会造成外部变量对象的修改。

深浅拷贝更多更详细内容见:
JavaScript基础心法 深浅拷贝(浅拷贝和深拷贝)
js 深浅拷贝 笔记总结

2、js内存机制

1)、js中内存的生命周期

  • 内存分配:当我们声明变量的时候,系统会自动为变量对象分配需要的内存
  • 内存使用:在分配到的内存中进行读/写操作
  • 内存回收:不再使用时将其销毁,释放内存

内存泄漏:不用的变量其内存未能及时释放。

2)、垃圾回收机制
js中有自动垃圾回收机制,会通过标记清除的算法识别哪些变量对象不再使用,对其进行销毁。开发者也可在代码中手动设置变量值为null(a = null)进行标记清除,让其失去引用,以便下一次垃圾回收时进行有效回收。

局部环境中,函数执行完成后,函数局部环境声明的变量不再需要时,就会被垃圾回收销毁(理想的情况下,闭包会阻止这一过程)。

全局环境下的变量只有页面退出时其生命周期才会结束。所以开发者应尽量避免在全局环境中创建全局变量,如需使用,也要在不需要时手动标记清除,将其内存释放掉。

详细的垃圾回收机制见:
JavaScript 内存机制
js内存管理机制

3)、为什么会有栈内存和堆内存之分?
通常与垃圾回收机制有关。为了使程序运行时占用的内存最小。

当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;

当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值