在 Javascript 中交换整个数组

Swap entire arrays in Javascript

当我尝试创建一个函数来交换 2 个数组时,原始数组保持不变。

function swap(x, y) {
    var temp = x; x = y; y = temp;
}

u=[1, 0];
v=[0, 1];
swap(u, v);
console.log(u);
console.log(v);

这导致 u 为 [1, 0],v 为 [0, 1]。在函数调用 swap 后,值没有改变。

另一方面,如果我在没有函数调用的情况下执行此操作:

u=[1, 0];
v=[0, 1];
var temp = u;
u = v;
v = temp;
console.log(u);
console.log(v);

然后它们被正确交换,u 为 [0, 1],v 为 [1, 0]。

我认为 Javascript 数组是按引用传递的,而不是按值传递的。我是不是误会了什么?

Javascript 无法传递对 uv 变量本身的引用。因此,在 swap() 函数中对 xy 的赋值不会改变对 uv 的赋值。 Javascript 传递对 uv 持有的对象的引用。因此,您无法从 swap() 中更改 uv 变量。您可以更改它们指向的对象的内容,因此可以修改 uv 指向的对象的属性。

由于我有 C/C++ 背景,所以我认为 Javascript 在传递对象时所做的事情是 "pass by pointer"。当您调用 swap(u, v) 时,传递给 swap() 函数的是指向 u 也指向的数组的指针。所以,现在你在同一个数组中有两个变量 ux 都 "pointing" 。因此,如果您修改该实际数组,那么由于 u 指向同一数组,因此两者都会看到修改。但是,您在 swap() 函数中所做的任何事情都不能改变 uv 实际指向的对象。


在 Javascript 中,更改原始变量指向的对象的唯一方法是使它们成为对象的属性并像这样传递对象:

function swap(obj, x, y) {
    var temp = obj[x]; obj[x] = obj[y]; obj[y] = temp;
}

var container = {};
container.u = [1, 0];
container.v = [0, 1];
swap(container, "u", "v");
console.log(container.u);
console.log(container.v);

如果您不介意从头开始重写两个数组,您可以将一个数组的所有内容复制到一个临时数组,然后将一个数组复制到另一个数组,然后将临时数组内容复制回第一个原始数组.这不是很有效,可能有更好的方法来解决您原来的问题,但可以做到。

 function swap(x, y) {
      // remove all elements from x into a temporary array
      var temp = x.splice(0, x.length);
      // then copy y into x
      x.push.apply(x, y);
      // clear y, then copy temp into it
      y.length = 0;
      y.push.apply(y, temp);
 }

它们是通过引用传递的,但它们也是通过引用赋值的。当你写 x = y 时,你并没有修改任何一个数组,你只是让你的局部变量 x 引用与 y.

相同的数组

如果你想交换数组内容,你必须修改数组本身:

function swap(x,y) {
    var temp = x.slice(0);
    x.length = 0;
    [].push.apply( x, y );
    y.length = 0;
    [].push.apply( y, temp ); 
}

获取这些 "reference/value" 问题的术语很棘手,但我会尽力而为。

您拥有的对象/数组变量实际上只是引用。与 C++ 不同,说 "x = y" 实际上并没有将对象的变量复制到新的内存位置。在内部,它只是复制一个指针位置。该语言没有构造 "automatically recreate" 新实例中的对象或数组之类的东西;如果出于某种原因,你想维护一个数组的两个副本,你将需要显式创建它然后复制值(即 = [];= new Array(); 或像 = oldArray.map(...) 这样的复制函数)

一个可能在概念上有所帮助的小代码示例。这些相同的规则适用于对象和数组。

a = {}; // In case you haven't seen it, this is like shorthand of "new Object();"
b = {};
c = b;
console.log(a === b); // false
console.log(b === c); // true
b.property = "hello";
console.log(c.property) // hello

就像 Java 一样,Java脚本 仅按值传递 。分配给函数中的局部变量永远不会对函数外的任何东西产生任何影响。

2022 年 2 月交换 2 个整个数组内容的解决方案。

您可以使用解构来交换两个数组:

let a = [  1,  2,  3, 4 ];
let b = ['a','b','c','d'];

[a,b] = [b,a];   // swap

console.log(a);  // ["a", "b", "c", "d"]
console.log(b);  // [1, 2, 3, 4, 5]

    let a = [  1,  2,  3, 4 ];
    let b = ['a','b','c','d'];
    
    [a,b] = [b,a];   // swap
    
    console.log(a);  // ["a", "b", "c", "d"]
    console.log(b);  // [1, 2, 3, 4, 5]

要交换 2 个数组,您可以使用

版本 1

let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];

let tempArr = [arrA, arrB];  // constructing new array
arrA = tempArr [1];
arrB = tempArr [0];

版本 1(人手不足)

let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
    
// RHS : construction a new array 
// LHS : destruction of array
[arrB, arrA ] = [arrA, arrB];  

版本 2(展开运算符)

let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];

let arrC = [...arrB]
arrB = [...arrA]
arrA = [...arrC]