对于函数的值传递和引用传递一直有点模糊理解。今天正好有空来扒一扒,首先看下关于这两个词的解释:
值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。 ——百度百科
引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。 ——百度百科
从定义来看,不管是值传递还是引用传递,都是针对参数来说的,也就是说只在变量当成参数传给函数时,才适用是值传递还是引用传递的讨论范围。
我们来看段代码:
function setName(arg){
arg.name = "Nicholas";
arg = new Object();//将函数局部变量obj指向另一个新的变量
arg.name = "Greg";
}
var person = new Object();
setName(person);//传递栈中的指针值
console.log(person.name);//Nicholas
用堆栈图表示:
函数的引用传递.png
通过堆栈图发现,javaScript在传递参数的时候实际上是把实际参数的地址传递到函数中。这跟我之前的理解就有点冲突了,之前没理清值传递与引用传递的概念,一直认为函数在传递参数的时候都是值传递。那照这样说,javaScrpit参数到底存不存在真正的值传递呢?
以我个人理解来看,并不存在,因为就算是基本数据类型当参数内存中也没必要额外复制一份地址,因为基本类型的值是不可变的。
我们来看以下代码:
function addTen(arg) {
arg = arg + 10;
return arg;
}
var count = 20;
var result = addTen(count);
console.log(count); // 20
console.log(result); // 30
从节约内存的角度来讲,应该是直接将参数arg指向实际参数count的地址,当有新值赋给arg时才将arg指向新值的地址。而不是一开始就在内存中造两个20。
由于基本类型的值是不变的,我们无法直接修改其值,所以只能用赋值符号("=")来赋予新的值。旧值如果没有被其他变量引用,就会被回收。
对应的堆栈图我们画出来:
基本类型参数传递.png我们把javaScript参数分为两类:
基本类型与引用类型
基本类型:String,Number,Boolean,Null,Undefined。
引用类型:Array、Object、Function、Date等有多个值构成的可变长度的复杂类型。
网上很多文章都把基本类型的函数传参解释为值传递,这样理解其实也是可以的,结果都一样,本着节省内存的角度,我认为引用传递更合理。
关于JavaScript变量赋值在内存中存储的问题可以看这篇文章:
javaScript变量在内存中的存储问题
网友评论
传入Map或者array,就是引用传递,函数里面改变参数的值,会对原对象有影响,除非new一个。