【问题标题】:Can I reassign a new array to an array variable in JavaScript?我可以将新数组重新分配给 JavaScript 中的数组变量吗?
【发布时间】:2018-07-30 07:46:47
【问题描述】:

我对 JavaScript 中的数组和在函数中操作它们有疑问。
这是Eloquent JavaScript 书中的一个练习。它是关于两个功能:

  • reverseArray():返回一个 new 数组,它与参数数组相反。
  • reverseArrayInPlace():只是反转参数数组本身。

在reverseArrayInPlace() 内部,我只是调用了reverseArray() 来创建一个新数组并重新分配给reverserArrayInPlace() 的参数。但是,当我显示传递的数组时,重新分配不会反映到传递的数组。
我认为 JavaScript 中的数组总是通过引用传递的?

我还尝试将一个数组变量重新分配给另一个数组,如果在函数之外完成它是成功的。可能是什么问题?
顺便说一句,练习禁止在 JavaScript 中使用 reverse() 方法。

function reverseArray(array) {
  var new_array = [];
  for (var i = array.length-1; i >= 0; i--)
    new_array.push(array[i]);
  return new_array;
}

function reverseArrayInPlace(array) {
  array = reverseArray(array);
}
	
var r1 = [1,2,3,4,5,6,7,8,9,10];

console.log("r1 ", r1.join(",")); 
// → 1,2,3,4,5,6,7,8,9,10

console.log("reverse of r1 ", reverseArray(r1).join(","));
// → 10,9,8,7,6,5,4,3,2,1

console.log("r1 ", r1.join(","));
// → 1,2,3,4,5,6,7,8,9,10

reverseArrayInPlace(r1);
// the changes are not reflected here

console.log("r1 reversed in place ", r1.join(",")); 
// → still 1,2,3,4,5,6,7,8,9,10;
// this should display r1 = 10,9,8,7,6,5,4,3,2,1

【问题讨论】:

  • JavaScript only 具有 Pass-By-Value(仍然允许 Call-By-Object-Sharing)。请在之前使用标签“Pass-By-Reference”搜索并清除这种混淆。
  • 无论如何,更改“没有反映出来”,因为提供的对象 没有变异(并且分配给参数对调用者没有影响因为 JavaScript only 有 Pass-By-Value;见上文。)
  • reverseArray 返回一个新数组 ...array = reverseArray(array); 将数组的 local(参数)引用分配给这个新数组,从而打破对传入数组,但不会更改传入的数组,因为它不会
  • 公平地说,@user2864740 ...谁想说pass-by-value a reference to an object:p
  • @JaromandaX 这就是我说“通过对象共享调用”的原因。它传达了预期的行为/语义并避免了“引用”的整个概念 - 在 ECMAScript 中 not 将其定义为“对对象的引用”并且定义不同(或根本没有)其他语言:}

标签: javascript arrays pass-by-value


【解决方案1】:

函数reverseArrayInPlace 的变量array 是该函数的本地变量。因此,分配给它只会使作用域忘记以前的值,即数组r1。

考虑以下几点:

var a = 5;
function change(a) {
  // Inner 'a'
  a = 0;
  console.log("inside change : ", a);
}

// Outer 'a'
change(a); // → 0
console.log("outside change : ", a); // → 5

可以看到,虽然全局作用域和change的作用域都使用了相同的名称a,但它们并不是同一个变量。在change 内部分配给a 永远不会影响外部a。

但是
对于一个对象(或所有Object.prototype 的实例,如数组),更改函数内部的属性将有效地更改它外部。

要完全理解这一点,请仔细查看以下内容:

var o = {
  arr1: [1, 2, 3],
  arr2: [1, 2, 3],
  str: "foo",
  num: 1
};

console.log("before changing : ", o);

function change(a) {
  // Reassigning to properties of 'a'
  a.arr1[0] = 0;
  a.arr2 = [ "destroyed" ];
  a.str += " bar";
  a.num = a.num * 15;
  
  // Reassigning to 'a'
  a = { change: "Destroyed !" };
  
  console.log("inside change : ", a);
}


change(o); // → { change: "Destroyed !" }
console.log("outside change : ", o); // → initial 'o' with modified properties.

分配给a = { change: "Destroyed !" }; 仍然没有影响o。但是对o 的属性所做的所有更改都已应用。

如您所见,更改o 的最终结果是:

{
  arr1: [0, 1, 3],     // First item changed.
  arr2: ["destroyed"], // It's a completely new array.
  str: "foo bar",      // " bar" was added.
  num: 15              // 1 * 15
}

【讨论】:

  • 不客气。不要忘记将问题标记为“已回答”:)
  • 我还是不明白这种行为是怎么发生的?为什么 JavaScript 仅在重新赋值时才将变量 a 视为单独的变量,而在我们更改 a 单个属性时则不然?
猜你喜欢
  • 2019-10-11
  • 2023-03-19
  • 2017-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多