js传参之值传递

2019-02-26  本文已影响0人  wojiaho

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'}


微信图片_20190226140047.png

我们再看代码3,前面的过程都是一样的

function change(v) {
  v = {};
  console.log(v); // {}
}

但是到了这边的时候,堆中会创建一个新的内存空间,用来存放{}(假设地址是0x0012),这时候会将v中的存放的0x0011这个地址替换成0x0012,此时v并不在0x0011,所以对0x0011中存放的value值并没有任何影响

所以代码3中value的输出还是{a: "a"}


微信图片_20190226154907.png

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

参考文档:https://github.com/mqyqingfeng/Blog/issues/10

上一篇 下一篇

猜你喜欢

热点阅读