在 Javascript 中交换整个数组

问题描述 投票:0回答:6

当我尝试创建一个函数来交换 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 arrays pass-by-reference pass-by-value
6个回答
8
投票

JavaScript 无法传递对

u
v
变量本身的引用。 因此,在
x
函数中对
y
swap()
的分配不会改变分配给
u
v
的内容。 JavaScript 传递对
u
v
所持有的对象的引用。 因此,您无法从
u
中更改
v
swap()
变量。 您可以更改它们指向的对象的内容,从而可以修改
u
v
指向的对象的属性。

由于我有 C/C++ 背景,我想到了 JavaScript 在将对象传递为“通过指针传递”时所做的事情。 当您调用

swap(u, v)
时,传递给
swap()
函数的是指向
u
也指向的数组的指针。 所以,现在你有两个变量
u
x
都“指向”同一个数组。 因此,如果您修改该实际数组,那么由于
u
指向同一个数组,因此两者都会看到修改。 但是,您在
swap()
函数内执行的任何操作都无法更改
u
v
实际指向的对象。


在 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);
 }

1
投票

获取这些“参考/价值”问题的术语很棘手,但我会尽力而为。

您的对象/数组变量实际上只是引用。与 C++ 不同,“x = y”实际上并不将对象的变量复制到新的内存位置。在内部,它只是复制一个指针位置。该语言没有在新实例中“自动重新创建”对象或数组之类的结构;如果出于某种原因,您想要维护数组的两个副本,则需要显式创建它,然后复制值(即

= [];
= 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

1
投票

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


0
投票

它们是按引用传递的,但也是按引用赋值的。当您编写

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 ); 
}

0
投票

2022 年 2 月交换 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]


0
投票

要交换 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]
© www.soinside.com 2019 - 2024. All rights reserved.