JS中全局变量作为函数实参传入的问题

昨天面试时,被问到了以下的JS代码问题,对比两种情况的输出思考为什么会是这样的结果

第一种情况
var a=[1,2,3];
function foo(a){
    a=[4,5,6];
}
foo(a);
console.log(a); // [1,2,3]1234567
第二种情况
var a=[1,2,3];
function foo(a){
    a.push(4);
}
foo(a);
console.log(a); // [1,2,3,4]1234567

被问的时候也是蒙圈的,回来仔细查了相关资料,总结一下,希望也能帮助到你理解这个问题。

看以上两种情况,当全局变量作为函数的实参传入函数之后被重新赋值,然而,执行完函数之后全局变量并没有发生改变,这是为什么?

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;123456789

我们看到全局变量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]123456789

再来看如下代码:

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]12345678

引用数据类型,会发现在函数里,形参被赋值之前,对形参调用引用数据类型的属性(或方法)时,不仅会改变形参,还会改变全局变量。这大概是同名形参和全局变量的一种对应吧,通俗解释一下就是只有当你在函数里被重新赋值之后,你才是独立的。而在这之前我们是穿一条裤子的,属性和方法的调用会同时改变我们。
希望对你有帮助。

posted @ 2022-10-26 15:10  青川薄  阅读(192)  评论(0编辑  收藏  举报