• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

值传递和引用传递和内存

武飞扬头像
王德发lxc
帮助1

目录

1.栈和堆

1.1栈结构及其相关存储属性

1.2堆结构及其相关属性

1.3图解栈和堆

2.拷贝

深拷贝


引言:我们在学习js过程中,也很想知道各种类型变量在内存中时如何存储的,今天我们讲学习这系列内容。

1.栈和堆

我们首先必须了解栈和堆两大概念,各种类型的变量就存储在这两者中

1.1栈结构及其相关存储属性

栈结构这里就不细讲了,详细大家之前学习中肯定了解栈结构的性质

在内存存储中,栈区中每一层叫做栈帧都占用栈本身有容量限制,超过限制为栈溢出

其中基本变量类型和数组地址值,对象的唯一访问地址值都存储在栈中

1.2堆结构及其相关属性

堆结构可以存储内存上连续的空间(数组),或者不连续的内存空间(对象)

1.3图解栈和堆

学新通

对于数组或者对象来说,堆内存中存储真实数据,然后地址值存储在栈中,需要访问他们时,只需要从栈中拿到地址值,然后拿着钥匙(地址值)去堆内存中拿数据

对于基本变量来说,就直接将真实数据存储到栈中

在实际开发中,这种存储方式也带来许多问题,下面来看一个案例:

  1.  
    var a= [1,2,3,4]
  2.  
    var b=1
  3.  
    var xx1=b
  4.  
    var x=a
  5.  
    console.log(xx1,x);//1,[1,2,3,4]
  6.  
    //当我们修改x的第一个值,然后打印原数组
  7.  
    var a= [1,2,3,4]
  8.  
    var b=1
  9.  
    var xx1=b
  10.  
    var x=a
  11.  
    console.log(xx1,x);//1,[1,2,3,4]
  12.  
    x[0]=9
  13.  
    console.log(a);//[9,2,3,4]

可以得到当操作xx1时,也会影响到,所以xx1和a在堆中指同一内存空间

但如果给xx1设置新的[1,2,3,4],及直接在xx1直接定义,两者将不会关联同一数组

将a=null时

只是将栈中的引用地址去掉,但是 堆内存中真实数据还会存在堆中,浏览器js引擎被垃圾回收地址收掉用来释放浏览器的运行内存

2.拷贝

什么是拷贝,我想从引用传递和拷贝的区别进行入手讲解:
先看下面代码

  1.  
    //引用传递
  2.  
    var arr=[1,2,3,4]
  3.  
    var arr1=arr
  4.  
    //拷贝
  5.  
    let arr2=[]
  6.  
    for(let i=0;i<arr.length;i ){
  7.  
    arr2.push(i)
  8.  
    }
  9.  
    //改变arr2
  10.  
    arr2[0]=3
  11.  
    console.log(arr2,arr);//arr[0]还是为0

引用传递和拷贝的区别:

引用传递两个数组访问的是堆内存中同一内存空间,而拷贝是在堆内存中重新申请一段内存,比如在案例中arr2和arr在堆中是两端不同的内存空间

正式介绍一下拷贝的概念,比如说数组拷贝相当于在内存中开辟一个新的内存空间,并且将原数组的所有内容风别按照下标复制一封放到新的数组,这样内存中会出现一个一样的数组,但是存储在不同的位置他们相互之间没有关系

但是这种方式为浅拷贝

深拷贝

 我们来通过浅拷贝和深拷贝的区别来认识深拷贝

先来看一个浅拷贝:

  1.  
    var arr=[{name:"a",age:17},{name:'s',age:18}]
  2.  
    var arr1=[]
  3.  
    for(let i=0;i<arr.length;i ){
  4.  
    arr1.push(i)
  5.  
    }
  6.  
    arr1[0].name='uuu'
  7.  
    console.log(arr,arr1);//arr的第一个对象中的name属性也为uuu
  8.  
    arr1.push(123)
  9.  
    log(arr,arr1)//只有arr1有123

观察结果来看,我们的拷贝还是浅拷贝,在内部赋值时还是会出现引用传递,也也就是出现影响原数组的问题,所以浅拷贝不能将对象的所有属性都进行复制,要想办法实现深拷贝

1.利用JSON.parse和JSON.stringify实现深拷贝

  1.  
    var arr=[{name:"a",age:17},{name:'s',age:18,},address:undefined]
  2.  
    var arr1=[]
  3.  
    for(let i=0;i<arr.length;i ){
  4.  
    arr1.push(i)
  5.  
    }
  6.  
    arr1[0].name='uuu'
  7.  
    console.log(arr,arr1);//arr的第一个对象中的name属性也为uuu
  8.  
    //先将arr转为字符串
  9.  
    var str=JSON.stringify(arr)
  10.  
    //然后将字符串转为一个反序列化一个新数组
  11.  
    var arr3=JSON.parse(str)
  12.  
    //此时验证一下,当修改arr3第一个对象的name属性时,原arr中对应的属性值会不会受到影响
  13.  
    arr3[0].name='iii'
  14.  
    console.log(arr,arr3);//没影响,arr中name属性还是原来的值

这就是一个深拷贝,我们观察结果,arr中的name属性并没有受到影响,所以代表时成功的

但是这个方法也有缺点,当我们原数组对象中包含函数或者带有原型链的对象 时,会导致数据丢失,比如说我们在原数组上添加一个函数,但是通过一系列操作后,会发现str和arr3都没有这个函数,

缺点二:观察结果,address这个属性不能被复制,即不能有undefined

第二种深拷贝的方式

  1.  
    var myobj={
  2.  
    name:'kerwin',
  3.  
    arr:[1,2,3]
  4.  
    }
  5.  
    var myobj2={
  6.  
    ...myobj
  7.  
    }
  8.  
    myobj2.name="xiaoming"
  9.  
    myobj2.arr.splice(1,1)
  10.  
    console.log(myobj);//通过控制台打印我们发现

通过控制台的打印,我们发现,此时myobj被影响到,此种拷贝方式其实只比拷贝多拷贝一层

在实际开发中我们都借助第三方库来实现(递归思想):比如说Immtable.js

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhhkifjg
系列文章
更多 icon
同类精品
更多 icon
继续加载