js传参之值传递
js数据存储方式
js中基本数据类型是存放在栈中;引用数据类型存在堆中,栈中会有一个内存空间存放引用数据类型的地址;
例如 var obj = {}
首先会在堆中开辟一个内存空间存放空对象(假设地址是0x0011),栈中也会开辟一个空间(假设地址是0x0021),0x0021中存放的内容就是0x0011,这个值指向堆中的空对象
ECMAScript中所有函数的参数都是按值传递的
值传递的意思是把函数外部的值复制给内部的参数
按值传递
// 代码段1
var value = "a";
function change(v) {
v = 'b';
console.log(v); // 'b'
}
change(value);
console.log(value); // 'a'
从这边我们可以看出来,当我们调用change方法的时候,传入的value,是将value的值复制一份然后传递进去,所以在change方法中改变了v的值,但是并不会影响value的值
然后我们再看下面的一段代码
// 代码段2
var value = {a: "a"};
function change(v) {
v.a = "b";
console.log(v); // {a: 'b'}
}
change(value);
console.log(value); // {a: 'b'}
如果按照上面的说法,这边输出的value应该不变啊,为什么这边的value却改变了呢?难道不是值传递,而是引用传递?
然后我们再看一段代码
// 代码段3
var value = {a: "a"};
function change(v) {
v = {};
console.log(v); // {}
}
change(value);
console.log(value); // {a: "a"}
看到这边,更加糊涂了,如果是引用传递,value输出的应该是{},为什么又不变了呢?
其实是因为,传入的参数如果是一个引用类型,那么实际上我们传进去的是这个变量的地址
首先我们分析一下代码2:
var value = {a: "a"};
此时在堆中创建一个内存空间,用于存放{a: "a"},假设地址为0x0011,在栈中会有一个内存空间(假设地址为0x0021),里面存放了0x0011这个地址,指向堆中存放的对象
change(value);
当我们调用change方法的时候传入的是value的地址,也就是0x0011
function change(v) {
v.a = "b";
console.log(v); // {a: 'b'}
}
这时,栈中会再次开辟一个内存空间(0x0022),用来存放刚刚传入的0x0011,此时修改v.a = "b",就将0x0011中的value的a属性修改了
所以代码2中最后console出来的value就是{a: 'b'}

我们再看代码3,前面的过程都是一样的
function change(v) {
v = {};
console.log(v); // {}
}
但是到了这边的时候,堆中会创建一个新的内存空间,用来存放{}(假设地址是0x0012),这时候会将v中的存放的0x0011这个地址替换成0x0012,此时v并不在0x0011,所以对0x0011中存放的value值并没有任何影响
所以代码3中value的输出还是{a: "a"}

所以javaScript高级程序设计中所说的"ECMAScript中所有函数的参数都是按值传递的",其实是如果是基本数据类型,传递值,如果是引用数据类型,传递地址(其实也就是地址值传递)