1. 原始值与引用值
JavaScript中变量可以分为两种类型,一种是原始值
,另外一种是引用值
。原始值就是基础类型的数据,引用值就是类似数组,对象,方法等由多个值构成的对象。
1.1 值的存储以及栈内存 / 堆内存
原始值包含有null, undefined, string, number, boolean, symbol
等六种,而引用值则包含有object, array, function, Date, Math
等... 。且原始值和引用值的存储位置也不同,原始值是存储在栈内存
中,而引用值则存储在堆内存中,而栈内存和堆内存的引用方式也不一样。首先我们来说一下栈内存。
栈内存: 我们在声明使用原始值变量时,栈内存会分配一块区域来存这个变量名和变量值,使用时也会在内存中直接调用这个变量。原始值在复制变量时是重新拷贝一份变量来的,就是在内存中再次分配一块儿区域给新复制的变量使用
let num1 = 5
let num2 = num1
如图所示,首先声明了一个变量num1
他的值为5,之后又声明了一个新的变量num2
,并将num1
的值赋给num2
,而在内存中展示的就是新开了一块内存空间,这里有点深拷贝的味道了
堆内存: 将一个引用值赋值给一个变量名时,这是数据存储在堆内存中,而且此时变量名的实际值并不是该引用数据,而是一个地址。为什么呢?是因为存储的时候引用值是存储在堆内存中,而同时生成了一个地址指向该引用值在堆内存中的位置,而变量名的值就是这个地址,每次访问数据或者修改引用值的时候都是通过这个地址的。
let obj = {name: '楚泽'}
let obj1 = obj
结合上面的代码和下面的图来说:声明了一个引用值,变量名是obj
,之后将obj
的值赋给了obj1
,但是实际上赋 obj1
的并不是引用值本身,而是它对应的保存在栈内存中的引用地址。引用地址不变,所以只想的引用值也是同一个不会变化的
1.1 值传递和引用传递
值传递: 就是在函数调用时传递一个基本类型的值,这个值发生变化后不会影响原本的值,如下面代码:
let num = 12
function fun(a){
a = 13
console.log(a)
}
fun() // 13
console.log(num) 12
代码中函数fun执行过程中将传进来的参数a
重新赋值为13,但是在函数外面打印num
时值时没有发生变化的。是因为函数体内a
重新赋值时,它的值是保存在栈内存中的,所以就重新分配了一个新的值,新值和外面的旧值时没有关联的。
引用传递: 引用传递就是在函数调用时使用参数传递进去一个引用值,但是这里在函数体内改变引用值属性的时候,作为参数传进去的引用值也会发生变化,但是这分为两种情况,一种是修改引用值,另一种是完全覆盖引用值
,采用完全覆盖的时候效果和值传递的效果是一样的,看代码
// 1. 修改引用值
let num = {}
function fun(a) {
a.name = '楚泽'
console.log(a)
}
fun(num) // {name: '楚泽'}
console.log(num) // {name: '楚泽'}
// 2. 覆盖引用值
let num = {}
function fun(a) {
a = []
console.log(a)
}
fun(num) // []
console.log(num) // {}
如代码所示,第一种情况是把变量 num
当作参数传到了方法中,但是仅对其添加了一个 name 属性,所以后面打印的时候两者都打印了相同的结果。
第二种情况是在方法体内直接将参数值给覆盖掉了,之后打印出来的结果和值传递的结果是一样的。这点以后日常开发需要注意到
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!