1.简单数据类型:
结合下图理解:
逐行代码分析理解
第一部分:
var num=10 声明了一个变量 同时会在栈内存中分配一个空间 直接把num的赋值10 存储到开辟的这个空间中 num就指向栈内存中的10
num=20 给num重新赋值为20 会直接在栈内存中找到num对应的这个值 直接替换成20 此时console.log(num)控制台打印的num就为会更新为20
第二部分:
在这里有一个function函数 函数不调用 不会执行 继续往下看 var x=10 声明了一个变量 同第一部分的在栈内存开辟一个空间存储x值10
fn(x) 调用了function函数 并携带一个x参数 那x就相当于等于10 所以function中形参a也就等于10 此时就等于又var声明了一个变量 (var a=10) 开辟了一个新的空间存储a值10 a就指向栈内存中的10 往下执行a++ 实际等于a=a+1 找到栈内存中a对应存储的值+1 此时a的值被更改为11 console.log(a) 打印的a值就为11
此时函数调用执行完毕 继续往下执行 console.log(x) 此时直接找到栈内存中的x 此时的x还是指向之前开辟的开辟空间 里面存储着10 所以还是等于10
所以 函数的形参可以看做是一个变量 把一个值类型变量作为参数给函数的形参时 其实是把变量在栈内存中复制了一份给形参 在栈内存中多了一份与外部变量一样的值 所以在方法内部做任何修改都不会影响外部变量
2.复杂数据类型传参:
逐行代码分析:
两个函数 不执行不会调用 往下看 var p=new Person('刘德华')
var p=new Person('刘德华')
有一个变量指向了一个复杂数据类型 (new了一下当然是复杂数据类型) 首先在栈内存中开辟了一片空间 与简单数据类型不同 它存储的是一个十六进制的地址 p会指向这个地址 真正的new Person('刘德华')是存放到堆内存里面的
函数内部 this指向当前创建的实例对象 也就是p this.name=name 它的name就等于刘德华
console.log(p.name) 会在内存中找到这个p 根据p存储的地址 去堆里面找到对应name的值 所以输出的是刘德华
往下执行 f1(p) 把p当做参数传递进去 相当于做了x=p这一步操作 此时在栈内存中开辟一个新的空间 并复制了一份p原先存储的地址 这个x指向复制的这个地址 console.log(x.name) 在栈内存中找到x指向的地址 他与p是同一个地址 所以在堆内存中 找到相对应存储的数据 name就等于刘德华
往下执行x.name=‘张学友’ 同上过程 通过地址找到堆里面存储的数据 把name从新复制为“张学友”
在console.log(x.name) 输出为张学友
往下执行 console.log(p.name) 输出的结果为张学友
因为在栈内存中 x是复制p地址 但是都同时指向堆内存中存储的数组 在函数内部对name进行了更新赋值 所以p.name也会随之更新
与简单数据类型传参不同 当把复杂数据类型也叫引用输入类型 传递给参数时 其实是把变量在栈空间存储的地址赋值给了形参 形参和实参保存的是一个地址 所以操作的是同一个对象