对于函数的值传递和引用传递一直有点模糊理解。今天正好有空来扒一扒,首先看下关于这两个词的解释:
值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。 ——百度百科
引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。 ——百度百科
注意: 这里的修改指的是对参数修改(用赋值符号“=”),而不是对参数的值进行修改。
从定义来看,不管是值传递还是引用传递,都是针对参数来说的,也就是说只在变量当成参数传给函数时,才适用是值传递还是引用传递的讨论范围。
我们来看段代码:
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在传递参数的时候实际上是把实际参数的引用副本传递到函数中(引用副本与引用指向同一个地址)。
综上所述,javaScript中参数的传递是值传递,这个值就是原变量的引用副本。
但是网上很多文章都说JavaScript中基本数据类型是值传递,Object类型是引用传递,是否正确呢?
不正确,值传递与引用传递的概念中,对参数的修改指的是用赋值方式修改,而非赋值方式修改则是对参数的值进行修改。
至于基本数据类型,由于基本数据类型的不可变性,所以是值传递。
我们来看以下代码:
function addTen(arg) {
arg = arg + 10;
return arg;
}
var count = 20;
var result = addTen(count);
console.log(count); // 20
console.log(result); // 30
由于基本类型的值是不变的,我们无法直接修改其值,所以只能用赋值符号("=")来赋予新的值。旧值如果没有被其他变量引用,就会被回收。这就是引用类型与基本类型传参的区别,直接对变量用"="赋予新值就相当于修改了该变量的引用地址。
对应的堆栈图我们画出来:
基本类型参数传递.png
我们把javaScript参数分为两类:
基本类型与引用类型
基本类型:String,Number,Boolean,Null,Undefined。
引用类型:Array、Object、Function、Date等有多个值构成的可变长度的复杂类型。
关于JavaScript变量赋值在内存中存储的问题可以看这篇文章:
javaScript变量在内存中的存储问题