JavaScript函数参数传值问题
首先先上个结论,在JavaScript中函数只有值传递,没有引用传递。
1.向参数传递基本数据类型
基本数据类型包括number、string这些。那么当传入这些基本类型时,是否可以通过形参来修改呢?
EXP:
var num = 123
function text(a){
a = 1
console.log(a) //1
}
text(num) // 1
console.log(num) //123
通过上面例子可以看到不可以通过形参的数值修改修改来改变实参的值,上面的代码其实等价于下面代码
var num = 123
function text() {
var a = num // 函数内部的参数变量,赋值函数外部的值
a = 1 // 修改内部变量的值
console.log(a) //1
}
text(num) // 1
console.log(num) // 123
通过上面的两个代码片段我们可以知道,其实当向参数传递基本数据类型的数值时,函数内的参数只是复制了传递来的值在栈中开辟了一个新的空间和实参num是完全不同的两个空间,所以修改了形参的值,只能改变自己并不会影响num本身。
2.向参数传递引用数据类型
引用数据类型包括数组、对象这些。那么是否可以通过修改参数的数组来改变实参的值呢?我们来看看下面的例子。
EXP:
let obj = {
name:'小红'
}
function text(o)
{
o.name = '小明'
}
text(obj)
console.log(obj.name) //小明
通过上面的例子我们可以看到当传递引用数据类型时,可以通过修改参数的值来改变实参的值,为什么呢?同理上面的代码等价与下面的代码:
let obj = {
name:'小红'
}
function text()
{
var o = obj //函数内部的参数变量,赋值函数外部的值,这个值其实是obj对象在堆内存中的地址值
o.name = '小明' //修改内部变量的值
}
text(obj)
console.log(obj.name) //小明
通过以上两段代码,我们可以知道当吃传递是引用数据类型时,传给参数的值其实是传递了对象在堆内存中的地址值,所以函数内部的参数o和obj都指向了同一个地址也就是同一个内存,所以修改了o的就等于修改了obj。
3.为什么说函数只有值传递没有引用传递
我们来看看下面这个例子:
function test(obj){
obj.name = "小红"
obj = new Object()
obj.name = "小明"
console.log(obj.name) //小明
}
var p = new Object()
test(p)
console.log(p.name) //小红
通过上面的运行结果我可以知道,我们把p的地址值传给了函数test的参数obj ,此时p和obj都指向了堆内存中的同一个地址,所以对obj的操作其实就是在这个地址上进行操作,所以相应的变化也会反应在p对象上。
然后,我们在对obj重新赋值后,这里就切断了obj和p间的地址联系,所以对obj的任何操作都不会反应到p对象上,因为两者间已经没有任何联系了。假设是引用传递的话那么obj = new Object() 就会等价于 p = new Object(),那么后面对obj的修改也会反应到p上 但是实际上并没用,说明不是引用传递。
总结
1.JavaScript中所有函数都是按照值传递的。
2.基本数据类型传递的是实际值,引用数据类型传递的的地址值。
3.基本数据类型作为形参时,不能通过改变形参来改变实参的数值。
4.引用数据类型作为形参时,可以通过改变形参来改变实参所指向空间的值。