值传递和引用传递和内存
目录
引言:我们在学习js过程中,也很想知道各种类型变量在内存中时如何存储的,今天我们讲学习这系列内容。
1.栈和堆
我们首先必须了解栈和堆两大概念,各种类型的变量就存储在这两者中
1.1栈结构及其相关存储属性
栈结构这里就不细讲了,详细大家之前学习中肯定了解栈结构的性质
在内存存储中,栈区中每一层叫做栈帧都占用栈本身有容量限制,超过限制为栈溢出
其中基本变量类型和数组地址值,对象的唯一访问地址值都存储在栈中
1.2堆结构及其相关属性
堆结构可以存储内存上连续的空间(数组),或者不连续的内存空间(对象)
1.3图解栈和堆
对于数组或者对象来说,堆内存中存储真实数据,然后地址值存储在栈中,需要访问他们时,只需要从栈中拿到地址值,然后拿着钥匙(地址值)去堆内存中拿数据
对于基本变量来说,就直接将真实数据存储到栈中
在实际开发中,这种存储方式也带来许多问题,下面来看一个案例:
-
var a= [1,2,3,4]
-
var b=1
-
var xx1=b
-
var x=a
-
console.log(xx1,x);//1,[1,2,3,4]
-
//当我们修改x的第一个值,然后打印原数组
-
var a= [1,2,3,4]
-
var b=1
-
var xx1=b
-
var x=a
-
console.log(xx1,x);//1,[1,2,3,4]
-
x[0]=9
-
console.log(a);//[9,2,3,4]
可以得到当操作xx1时,也会影响到,所以xx1和a在堆中指同一内存空间
但如果给xx1设置新的[1,2,3,4],及直接在xx1直接定义,两者将不会关联同一数组
将a=null时
只是将栈中的引用地址去掉,但是 堆内存中真实数据还会存在堆中,浏览器js引擎被垃圾回收地址收掉用来释放浏览器的运行内存
2.拷贝
什么是拷贝,我想从引用传递和拷贝的区别进行入手讲解:
先看下面代码
-
//引用传递
-
var arr=[1,2,3,4]
-
var arr1=arr
-
//拷贝
-
let arr2=[]
-
for(let i=0;i<arr.length;i ){
-
arr2.push(i)
-
}
-
//改变arr2
-
arr2[0]=3
-
console.log(arr2,arr);//arr[0]还是为0
引用传递和拷贝的区别:
引用传递两个数组访问的是堆内存中同一内存空间,而拷贝是在堆内存中重新申请一段内存,比如在案例中arr2和arr在堆中是两端不同的内存空间
正式介绍一下拷贝的概念,比如说数组拷贝相当于在内存中开辟一个新的内存空间,并且将原数组的所有内容风别按照下标复制一封放到新的数组,这样内存中会出现一个一样的数组,但是存储在不同的位置他们相互之间没有关系
但是这种方式为浅拷贝
深拷贝
我们来通过浅拷贝和深拷贝的区别来认识深拷贝
先来看一个浅拷贝:
-
var arr=[{name:"a",age:17},{name:'s',age:18}]
-
var arr1=[]
-
for(let i=0;i<arr.length;i ){
-
arr1.push(i)
-
}
-
arr1[0].name='uuu'
-
console.log(arr,arr1);//arr的第一个对象中的name属性也为uuu
-
arr1.push(123)
-
log(arr,arr1)//只有arr1有123
观察结果来看,我们的拷贝还是浅拷贝,在内部赋值时还是会出现引用传递,也也就是出现影响原数组的问题,所以浅拷贝不能将对象的所有属性都进行复制,要想办法实现深拷贝
1.利用JSON.parse和JSON.stringify实现深拷贝
-
var arr=[{name:"a",age:17},{name:'s',age:18,},address:undefined]
-
var arr1=[]
-
for(let i=0;i<arr.length;i ){
-
arr1.push(i)
-
}
-
arr1[0].name='uuu'
-
console.log(arr,arr1);//arr的第一个对象中的name属性也为uuu
-
//先将arr转为字符串
-
var str=JSON.stringify(arr)
-
//然后将字符串转为一个反序列化一个新数组
-
var arr3=JSON.parse(str)
-
//此时验证一下,当修改arr3第一个对象的name属性时,原arr中对应的属性值会不会受到影响
-
arr3[0].name='iii'
-
console.log(arr,arr3);//没影响,arr中name属性还是原来的值
这就是一个深拷贝,我们观察结果,arr中的name属性并没有受到影响,所以代表时成功的
但是这个方法也有缺点,当我们原数组对象中包含函数或者带有原型链的对象 时,会导致数据丢失,比如说我们在原数组上添加一个函数,但是通过一系列操作后,会发现str和arr3都没有这个函数,
缺点二:观察结果,address这个属性不能被复制,即不能有undefined
第二种深拷贝的方式
-
var myobj={
-
name:'kerwin',
-
arr:[1,2,3]
-
}
-
var myobj2={
-
...myobj
-
}
-
myobj2.name="xiaoming"
-
myobj2.arr.splice(1,1)
-
console.log(myobj);//通过控制台打印我们发现
通过控制台的打印,我们发现,此时myobj被影响到,此种拷贝方式其实只比拷贝多拷贝一层
在实际开发中我们都借助第三方库来实现(递归思想):比如说Immtable.js
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhhkifjg
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
微信运动停用后别人还能看到步数吗
PHP中文网 07-22