今天偶然被朋友问到一个问题,推翻了自己以往的认知。
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);
问题:
- 为什么变量 a 没有被更改为 [2,3,4]呢?
- 函数在执行的时候 形参 x 和实参 a 是什么关系呢?
今天偶然被朋友问到一个问题,推翻了自己以往的认知。
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答案:**
在JavaScript中,当你将一个对象(例如数组)作为参数传递给函数时,实际上传递的是对该对象的引用,而不是对象的副本。因此,当你尝试在函数内部修改参数`x`时,你实际上是在修改原始数组`a`。这就是为什么`a`没有被更改为`[2,3,4]`的原因。
**问题2答案:**
在函数执行时,形参`x`和实参`a`的关系是引用关系。它们都指向同一个数组对象。这就是为什么在函数内部修改`x`的值也会影响到`a`的原因。这种行为称为按值传递,但实际上是按引用传递,因为数组和对象是通过引用传递的。
因为 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);
10 回答11.3k 阅读
5 回答4.9k 阅读✓ 已解决
4 回答3.2k 阅读✓ 已解决
2 回答2.8k 阅读✓ 已解决
3 回答5.2k 阅读✓ 已解决
1 回答3.3k 阅读✓ 已解决
3 回答2.4k 阅读✓ 已解决
形参大概可以认为是拷贝了实参的值或者引用地址。这里x作为函数test的形参,在执行时,因为a是一个数组,所以x拷贝的是a的引用。
在第一个log中,控制台输出true,是因为此时x和a指向的是同一个地址;然后你通过重新赋值改变了x的指向,此时a仍然指向的是原地址,所以会有后面两个不同的打印结果。