JS中全局变量作为函数实参传入的问题
昨天面试时,被问到了以下的JS代码问题,对比两种情况的输出思考为什么会是这样的结果
第一种情况
var a=[1,2,3];
function foo(a){
a=[4,5,6];
}
foo(a);
console.log(a); // [1,2,3]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
第二种情况
var a=[1,2,3];
function foo(a){
a.push(4);
}
foo(a);
console.log(a); // [1,2,3,4]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
被问的时候也是蒙圈的,回来仔细查了相关资料,总结一下,希望也能帮助到你理解这个问题。
看以上两种情况,当全局变量作为函数的实参传入函数之后被重新赋值,然而,执行完函数之后全局变量并没有发生改变,这是为什么?
JS高级程序设计第三版70页有阐述。加上自己的理解总结如下:
原本的b=a有两种赋值方式,一种是按值,另一种是按引用。
ECMAScript中所有的参数传递都是按值传递的,也就是说把函数外部的值复制给函数内部的参数,无论是基本类型还是对象类型,实参和形参都会指向不同的内存地址,并且作用域不同,形参的作用域仅仅在函数体内。
我们看如下代码:
var a=[1,2,3],
var b=1;
function foo(a,b){
a=[4,5,6];
b=2;
}
foo(a,b);
console.log(a); // [1,2,3]
console.log(b); //1;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
我们看到全局变量a和b,被作为实参传给形参后,函数体内对变量a、b进行了重新的赋值,但是并没有改变全局变量a、b的值,即说明函数体内的a、b赋值都是对形参的赋值,形参与在函数中声明的变量一样有着相同的性质。
但是有一种情况比较特殊,但是不会违背参数按值传递的规律。看如下代码:
var a=[1,2,3];
function foo(a){
a.push(4); //调用引用类型方法,改变了形参a,也改变了全局变量a
console.log(a); // [1,2,3,4] 此时的a是形参变量的值
a=[5,6,7]; // 形参重新赋值不会改变全局变量a
console.log(a); // [5,6,7] 形参变量a
};
foo(a);
console.log(a); // [1,2,3,4]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
再来看如下代码:
var a=[1,2,3];
function foo(a){
a=[5,6,7]; // 形参a被重新赋值,不会改变全局a
a.push(4); // 此时只改变了形参a,不会改变全局a
console.log(a); // [5,6,7,4]
};
foo(a);
console.log(a); // [1,2,3]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
对引用数据类型,会发现在函数里,形参被赋值之前,对形参调用引用数据类型的属性(或方法)时,不仅会改变形参,还会改变全局变量。这大概是同名形参和全局变量的一种对应吧,通俗解释一下就是只有当你在函数里被重新赋值之后,你才是独立的。而在这之前我们是穿一条裤子的,属性和方法的调用会同时改变我们。
希望对你有帮助。