代码输出问题?

function f(a){

a.x = 1;
console.log(a.x);//1
a = { x: 3 };
console.log(a.x);//3

}
var a = { x: 0 };
f(a);
console.lo(a.x);//1
打印结果:
1
3
1
请问最后一个打印结果为什么是1,第4行声明的是全局变量吗

阅读 1.8k
3 个回答

整个调用过程如图所示。示意图

另,如果函数 f 没有形参,则所有操作就会是针对全局变量 a 及其所指向的对象;

function f(){
  a.x = 1;         //修改 "对象1" 的 x 为 1
  console.log(a.x);//1 打印 "对象1" 的 x 
  a = { x: 3 };    //改变 "全局变量a" 指向 "对象2"
  console.log(a.x);//3 打印 "对象2" 的 x 
}
var a = { x: 0 };  //初始 "全局变量a" 指向 "对象1"
f();
console.log(a.x);  //3 打印 "对象2" 的 x 

# 打印结果变为: 1 3 3

JS中函数的参数都是按值传递的,可以理解为是个副本。

重点是a = { x: 3}这一步操作导致了这个结果。

函数的参数a其实和你声明的全局变量a本身不是同一个东西(参数是一个副本),但是由于a是一个对象,属于引用类型,都是同一个内存地址,也就是他们此时还是相等的。所以a.x = 1这句代码,等同于修改了原始的a对象。但是你后面的操作a = { x: 3}, 将对象完全赋值给a这个副本后,那么这个内存地址里就不是原始对象a了,等同于将参数a和原始对象a的引用切断,从这里开始他们便不再相等。所以紧接着打印的a.x为3,是副本a的值。后面再打印的a.x是原始a的值。此时两个a已经完全不相等了。

在函数内对形参对象实例进行“重新赋值”(改变其引用)不会影响到实参,有些语言提供了in,out参数来适用这种场景,js没有提供,但可以使用返回值或加入context参数让上层接收到新对象引用

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题