本文转 SegmentFault 社区
社区专栏:夕阳下的奔跑
作者:G_Koala_C
起因是在逛 sf 的时候看到这样一个问题:
Javascript 为什么 arr 数组没有被赋值?var arr=[1,2];
var arr0=[{a:1,b:2}];
function fun(data){
data = arr0
}
fun(arr);
console.log(arr) //[1,2]
问题:调用函数后 arr 的值不是应该改变的吗?为什么 arr 的值没有改变?提问者:smile_梵音
一看这个问题,似懂非懂。后经讨论和高人指定,画了下内存图,感觉瞬间清晰了。和大家分享下,欢迎指正!初始的内存分布,形参变量存在栈中,对象存在堆内。如图,栈中有 arr,arr0,还有 fun 的形参 data 三个变量,分别指向了堆中的两个数组对象的首地址。执行 fun(arr);,将 arr 数组对象的首地址作为实参传入 fun 中,此时,data 的指向发生变化,指向了 arr 数组对象的首地址。如图:最后 console.log(arr);,输出 arr,由于 arr 依然指向的是原来的 arr 数组对象,所以输出没有变化。那么,再看下另外的情况
var arr=[1,2];
var arr0=[{a:1,b:2}];
function fun(data){
data[0] = 3;
data[1] = 4;
}
fun(arr);
console.log(arr) //[3,4],这里的arr的值为什么又变了呢?
直接开始 fun(arr);,data 指向 arr 数组对象的首地址,拿到了 arr 对象的操作权限。方法内部,data 对 arr 数组对象的值进行了修改(暂不考虑越界的问题)。结果如图:所以最后 arr 被改变了。两种代码不同的地方是,一个没改变对象本身,只是指针发生了变化。另一个是用心的指针操作了对象,所以原指针指向的数据就发生了变化。另外存在引用传递和值传递的误区。编程的道路,因为分享越来越宽!
参考社区问题:https://segmentfault.com/q/1010000022157769?_ea=35791954https://segmentfault.com/q/1010000022159540?_ea=35774822
部分社区用户回答内容:Javascript 变量,实际是一个到对象的 binding 。赋值只修改 binding ,不修改对象。 但是 a.b = 会修改 a 绑定的对象的 b 属性的 binding ,于是改变了 a 绑定的对象(因为它的一个属性变化了。)回答者:fefe
js 函数传参全部都是值传递!对于原始类型,存放在栈内存中,变量传递赋值的时候是值传递,这个没什么好说的!对于对象(object,arr,function等)来说,存放在堆内存中,变量的值其在堆内存中的地址,函数传参的时候,对于这类数据,传递的是地址的值,也是按值传递。函数内的变量和函数外的变量都是存放同一个对象在堆内存的地址,都可以改变其属性数据。回答者:hfhan
- END -