Javascript 是不是通过引用或值将数组传递给函数?

Posted

技术标签:

【中文标题】Javascript 是不是通过引用或值将数组传递给函数?【英文标题】:Does Javascript pass array to function by reference or value?Javascript 是否通过引用或值将数组传递给函数? 【发布时间】:2016-06-19 00:20:48 【问题描述】:

据我了解,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的数据?

【问题讨论】:

***.com/questions/518000/… 重复。简短回答:Javascript 总是按值传递,数组/对象除外。 JavaScript 总是按值(复制)。但是,对于对象,值是一个引用(按值引用)。 Is JavaScript a pass-by-reference or pass-by-value language? 你所期望的是一个指针,其中outTestArray 引用了aiTest,这是 JavaScript 所没有的。 我认为问题出在 slice(0) 函数上。因为如果在函数 testFunc() 我修改如下: outTestArray[0] = 1; outTestArray[1] = 2;...然后将aiTest传递给这个函数,aiTest就会改变。 @TrungNguyen 问题是=。通过分配outTestArray,您可以修改它的值。但是,aiTest 仍然指的是原始数组。 outTestArray[1] = 2 行为不同的原因是因为它修改了数组本身而不是修改任何一个变量。 【参考方案1】:

函数参数就像新的变量赋值,它不像 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();
...

【讨论】:

【参考方案2】:

在您的代码中,testFunc 获取对复制到参数outTestArray 中的原始数组的引用。在函数体中,您使 outTestArray 指向不同的数组。如果你想改变原来的数组,那么你可以说

outTestArray.splice(0, outTestArray.length, ...aiTemp)

请注意,扩展运算符用于aiTemp

【讨论】:

【参考方案3】:

你的错误在于你对浅拷贝的概念是错误的。

浅拷贝复制数组的内容,但不复制数组成员引用的东西。

如果您的数组是对对象的引用数组,则浅拷贝将复制引用,因此您的新数组将指向相同的底层对象。

但是这个数组是整数。整数本身被浅拷贝复制。

【讨论】:

正如你所说的“整数本身被浅拷贝复制。”是的,我知道这一点。但这与为什么aiTest在out of function后没有变化无关? 数组通过引用副本传递。 testFunc 的 outTestArray 是对底层数组的引用。您的 aiTemp 分配将该 reference 设置为指向新数组 [1,2,3,4]。然后你出于某种原因复制它。您不是在修改引用后面的数组,而是在修改 reference 本身 明确地说,你可以通过改变底层数组来修改它,比如outTestArray[0] = 1。这将修改您的aiTest 的第一个值。 所以:赋值修改引用。对象通过复制引用传递。但是您仍然可以通过调用更新其状态的函数或其他方式来改变对象。

以上是关于Javascript 是不是通过引用或值将数组传递给函数?的主要内容,如果未能解决你的问题,请参考以下文章

通过引用或值传递的数组[重复]

使用 JNI(更具体地说是 Android NDK)时,Java 是不是通过引用或值传递给 C

将 lambda 作为参数传递 - 通过引用或值?

通过引用或值传递对象

在 C# 中通过引用或值传递对象

JavaScript - 通过引用传递时清空数组/对象问题