js关于函数参数和实参是什么关系?

今天偶然被朋友问到一个问题,推翻了自己以往的认知。

const a= [1,2,3];
function test(x){
   console.log(x===a)// 控制台输出 true
    x=[2,3,4]   
    console.log(a); // 依旧为[1,2,3]
    console.log(x); //变为[2,3,4]
};
test(a);

问题:

  1. 为什么变量 a 没有被更改为 [2,3,4]呢?
  2. 函数在执行的时候 形参 x 和实参 a 是什么关系呢?
阅读 1.3k
avatarAI BotBETA
**问题1答案:**
在JavaScript中,当你将一个对象(例如数组)作为参数传递给函数时,实际上传递的是对该对象的引用,而不是对象的副本。因此,当你尝试在函数内部修改参数`x`时,你实际上是在修改原始数组`a`。这就是为什么`a`没有被更改为`[2,3,4]`的原因。

**问题2答案:**
在函数执行时,形参`x`和实参`a`的关系是引用关系。它们都指向同一个数组对象。这就是为什么在函数内部修改`x`的值也会影响到`a`的原因。这种行为称为按值传递,但实际上是按引用传递,因为数组和对象是通过引用传递的。
5 个回答

形参大概可以认为是拷贝了实参的值或者引用地址。这里x作为函数test的形参,在执行时,因为a是一个数组,所以x拷贝的是a的引用。
在第一个log中,控制台输出true,是因为此时x和a指向的是同一个地址;然后你通过重新赋值改变了x的指向,此时a仍然指向的是原地址,所以会有后面两个不同的打印结果。

关于函数的形参你可以这样理解:

function fn(let x) {
    
}
//当你使用的时候
let arr = [1, 2];
fn(let x = arr) {
    
}
````

大概是这样子

因为 a[1,2,3] 的引用,所以函数的实参 x 也是 [1,2,3] 的引用。你把 x 赋值为 [2,3,4] 是修改了 x 的指向,而没有修改 a 的指向。


如果你是在函数内直接修改原对象的属性,那么就会同时更改两者的值:

const a= [1,2,3];
function test(x){
    x.splice(1, 1)
    console.log(a); // [1,3]
    console.log(x); //[1,3]
};
test(a);

x是a的引用地址,你没有通过x.属性名去修改堆内存的东西,而是直接把x替换了一个地址,就导致x跟a的引用地址变得不一致。

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