为什么在JavaScript中我不能交换两个变量?

3

我试图在JavaScript中交换两个变量,但我的代码无法正常工作。有人能告诉我原因吗?

我认为这应该返回10, 5,因为我已经调用了swap函数。但实际上,它返回的是5, 10。

function swap(a, b) {
  var temp = a;
  a = b;
  b = temp
}

var x = 5;
var y = 10;
swap(x, y);
console.log(x, y);


1
x和y没有通过引用传递,它们的值被复制在a和b中。 - vrintle
JavaScript通过值(或“共享”)传递参数,而不是通过引用。https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing - JLRishe
4个回答

4

JavaScript和Java一样,只支持按引用传递。这意味着虽然您的函数确实交换了值,但在调用范围内,xy的实际值没有被交换。在这里的一个解决方法可能是返回一个数组,其中包含已经交换的值:

function swap(a, b) {
    return [b, a];
}

var x = 5;
var y = 10;
[x, y] = swap(x, y);
console.log("x after swap = " + x);
console.log("y after swap = " + y);

请注意,这里的关键是赋值语句:
[x, y] = swap(x, y);

这将xy在一行中交换数组的值。

注意,这与编写 var x = 5, y = 10; [x,y] = [y,x] 相同。如果您要依赖解构赋值,那么函数的用处不大。 - Mulan

2
您可以使用解构赋值方法:
let a = 1;
let b = 2;

[a, b] = [b, a];

a; // => 2
b; // => 1

1
你可以使用JavaScript的对象来实现这一点,它们通过共享传递,类似于你在其他语言中可能经历过的按引用传递。这使你能够做一些使用原始值不可能做到的事情 -

function ref (value) {
  return { value }
}

function deref (t) {
  return t.value
}

function set (t, value) {
  t.value = value
}

function swap (a, b) {
  const temp = deref(a)
  set(a, deref(b))
  set(b, temp)
}

const x = ref(3)
const y = ref(5)
swap(x,y)
console.log(deref(x), deref(y)) // 5 3

你可以以任何方式进行这种抽象 -

const box = v => [v]
const unbox = t => t[0]
const set = (t, v) => t[0] = v

function swap (a, b) {
  const temp = unbox(a)
  set(a, unbox(b))
  set(b, temp)
}

const x = box(3)
const y = box(5)
swap(x,y)
console.log(unbox(x), unbox(y)) // 5 3


2
对象不是通过引用传递的。它们是通过“共享”传递的,这是传值的一个子类别。 - JLRishe
感谢您提供技术上正确的术语,尽管维基百科称其并不常用。 - Mulan

1
Javascript函数值不是通过引用传递的,而是在a、b中复制了这些值。因此,应该返回值:
function swap(a, b) {
  return [b, a];
}

稍后获取它:
[x, y] = swap(x, y);

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