使用解构赋值交换元组元素

Swap tuple elements with destructuring assignments

我想使用解构赋值就地交换元组的元素,如下所示:

var a = [1,2];
[a[1], a[0]] = a;

但是,这会产生 [1, 1]

Babel 将其编译为

a[1] = a[0];
a[0] = a[1];

我原以为这应该编译为

let tmp0 = a[0];
let tmp1 = a[1];
a[0] = tmp1;
a[1] = tmp0;

Traceur 的行为与 babel 相同。所以我想这是指定的行为?

我想原地交换两个元素。唯一的方法就是...

let tmp = a[0];
a[0] = a[1];
a[1] = tmp;

但我认为以上是解构赋值应该让我避免不得不做的事情。

我完全有能力颠倒数组中两个元素的顺序,所以这不是我的问题。我可以做一些像 a.push(a.shift()) 这样简单的事情,它满足就地交换的标准。

我最感兴趣的是为什么解构没有按照它看起来应该的方式工作。

这个怎么样:

var a = [1,2];
a = a.reverse();

作为替代方法,您可以使用 slice:

var a = [1,2];
[a[1], a[0]] = a.slice();
a; // [2,1]

I would have thought this should be compiled as

let tmp0 = a[0];
let tmp1 = a[1];
a[0] = tmp1;
a[1] = tmp0;

不,在分配值之前不会检索这些值。或者也不是从中检索值的 a 的副本。只有一个对数组的引用;您的代码宁愿脱糖

{
    const tmp = a;
    a[1] = tmp[0];
    a[0] = tmp[1]; // here, tmp[1] has the "wrong" value because a===tmp
}

或者实际上,它脱糖为迭代数组的迭代器,同时 […] 中的左侧引用被分配给。

我只想使用一个函数来做到这一点

let swap = ([a,b]) => [b,a];

swap([1,2]); // => [2,1]

这适用于支持解构的 Firefox:

(function () {
  "use strict";

  var a = [0, 1];
  [a[1], a[0]] = [a[0], a[1]];
  console.log(a);//[1, 0]
}());