JavaScript将数组传递给函数是按引用还是按值传递?

7
据我了解,JavaScript传递对象时是按引用传递的,而数组也是一种对象,但当我创建一个整数数组并将其作为下面代码所示传递给函数时:
function testFunc(outTestArray) {
  var aiTemp = [1,2,3,4];

  /*Using slice(0) to clone array */
  outTestArray = aiTemp.slice(0);
}

var aiTest = Array.apply(null, Array(4)).map(Number.prototype.valueOf, 0);
testFunc(aiTest);

console.log(aiTest.toString()); // aiTest still [0,0,0,0]

我知道slice(0)函数只返回数组的浅拷贝,但如果该数组仅是一个整数数组,则我的问题是为什么aiTest的数据没有被修改?

1
https://dev59.com/5nRB5IYBdhLWcg3wxZ7Y - MONTS_MIND_Hacker
2
重复。简短回答:Javascript始终是按值传递,除了数组/对象。 - Max
1
JavaScript 总是按值(复制)。不过,对于对象来说,其值是一个引用(按引用传递)。JavaScript 是按引用还是按值传递的语言? 你期望得到的是一个指针,其中 outTestArray 引用回 aiTest,但是 JavaScript 没有这个功能。 - Jonathan Lonowski
我认为问题出在slice(0)函数上。因为如果在testFunc()函数中我这样修改:outTestArray [0] = 1; outTestArray [1] = 2;...然后将aiTest传递给此函数,那么aiTest将被更改。 - Trung Nguyen
@TrungNguyen 这个问题在于 =。通过赋值 outTestArray,您修改了它的值。但是,aiTest 仍然指向原始数组。outTestArray[1] = 2 表现不同的原因是因为它修改了数组本身而不是修改任何变量。 - Jonathan Lonowski
3个回答

2

函数参数就像新的变量赋值,而不是C语言中的引用或指针。它更像是这样的:

function testFunc(...args) {
  var outTestArray = args[0];
  var aiTemp = [1,2,3,4];

  /*Using slice(0) to clone array */
  outTestArray = aiTemp.slice(0);
}
...

如您所见,在上述代码中,您正在克隆数组并将其分配给函数内范围的变量outTestArray,该变量在函数外部不可访问。

您可以使用闭包来实现您想要的功能:

var outerArray;
function testFunc(array) {
  var aiTemp = [1,2,3,4];
  outerArray= aiTemp.slice(0);
}

或者更好的方法是,只需返回一个新数组:
function getArray() {
  return [1,2,3,4];
}

var aiTest = getArray();
...

0
你的错误在于你对浅复制的概念是错误的。
浅复制会复制数组的内容,但不会复制数组成员所指向的内容。
如果你的数组是对象引用数组,那么浅复制会复制这些引用,所以你的新数组将指向相同的底层对象。
但这个数组是整数数组。整数本身会被浅复制复制。

正如你所说,“整数本身通过浅拷贝被复制。”是的,我知道这一点。但这与为什么在函数外部aiTest没有改变无关。 - Trung Nguyen
1
该数组是通过“引用的副本”传递的。testFunc的outTestArray是指向底层数组的引用。您的aiTemp赋值将该“引用”设置为指向新数组[1,2,3,4]。然后您因某种原因复制它。您没有修改引用后面的数组,而是修改了“引用本身”。 - Chris Kitching
要清楚,您可以通过执行某些可变异的操作(例如 outTestArray[0] = 1)修改基础数组。这将修改您 aiTest 的第一个值。 - Chris Kitching
1
因此:赋值会修改引用。对象通过复制引用传递。但是您仍然可以通过调用更新其状态或其他方式更新它们的函数来改变对象。 - Chris Kitching

0
在你的代码中,testFunc 获取了对原始数组的引用,该数组被复制到参数outTestArray中。在函数体中,你将outTestArray指向另一个数组。如果你想改变原始数组,那么你可以这样说:
outTestArray.splice(0, outTestArray.length, ...aiTemp)

请注意,扩展操作符正在用于aiTemp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接