在探究函数参数传递之前,我们需要了解一下JS中的数据类型与内存。
JS中分为基本数据类型和引用数据类型。对于基本数据类型,他们的变量名和值是直接存在栈空间中国的。而对于引用数据类型,他们的值存在堆空间,栈空间存变量名,和指向堆空间内存的地址。
红宝书中有一句话,JS函数都是按值传参的。对于基本数据类型,很好理解。对于引用类型,我开始一直没绕出来,直到把这么数据类型的存储方式给结合起来之后,才体会到。
这里有一个例子:
let obj = {};
function changeValue(obj) {
obj.name = 'ConardLi';
obj = {name:'Conardli秘密花园'}
}
changeValue(obj);
console.log(obj.name);
你觉得会打印出什么?ConardLi还是Conardli秘密花园?
答案是ConardLi。
我们从内存的角度来分析分析
栈内存中:
key | value |
---|---|
对象obj | 0*000001 |
形参obj | 0*000001 |
在obj = {name:‘Conardli秘密花园’}这句代码之前,对象obj和形参都指向同一地址,里面存的是对象的值。当执行obj = {name:‘Conardli秘密花园’}时,形参obj会指向一段新的内存地址,用来保存形参obj的值
let obj = {};
function changeValue(obj) {
obj.name = 'ConardLi';
obj = {name:'Conardli秘密花园'}
console.log(obj.name);
}
changeValue(obj);
console.log(obj.name);
当我执行这段代码时,函数体里面打印出来的是Conardli秘密花园。
总结一下:函数参数传递的并不是变量的引用,而是变量拷贝的副本,当变量是原始类型时,这个副本就是值本身,当变量是引用类型时,这个副本是指向堆内存的地址