Inverting two values with destructuring
Published on 10 May 2020 • 3 min

Cette page est également disponible en français.

Here comes the seventh article of our daily series “19 nuggets of vanilla JS.” Are you still going through a temporary variable when inverting two values? You’re Doing It Wrong!™

The series of 19

Check out surrounding posts from the series:

  1. Strings and Unicode
  2. Short-circuiting nested loops
  3. Inverting two values with destructuring (this post)
  4. Easily stripping “blank values” from an array
  5. Long live numeric separators!
  6. …and beyond! (fear not, all 19 are scheduled already)…

Ye Olde Way

Numerous algorithms require inverting two variables. You’ll need that in hash computations, sorts, math sequences, and more. Long story short, we’ve needed this ever since programming was a thing (which, if only in its modern form, has been roughly 70 years). But the first widespread programming languages had no specific mechanism for this, so we’ve needed to go through a temporary variable.

Let’s say we need to invert the values of A and B. The three-step dance is always the same, and considering we’re only talking about assignments, the syntax will be identical in most widespread languages:

  1. We “backup” the initial value of A in, say, TMP.
  2. We copy the value of B in A.
  3. We copy A’s former value (backed up in TMP), in B.

This boils down to some kickass, prize-worthy code:

let tmp = a
a = b
b = tmp

Not that exciting, I’m afraid.

A quick reminder on destructuring

The term destructuring generally refers to obtaining multiple data at once from some piece of structured data.

Since ES2015, JavaScript has offered two kinds of destructuring:

  • Positional (“array”) destructuring is based, as its name implies, on the positions of values in the source data, which can be anything iterable, and most often is an array. That type of destructuring is surrounded by square brackets ([]).
  • Named (“object”) destructuring relies on the names of properties in the source data, which can be any object. The order thus does not matter. This type of destructuring is surrounded by curly braces ({}).

You can’t destructure null or undefined, but anything else is fair game.

Finally, you can put a destructuring anywhere there is an assignment, be it…

  • explicit (assignment operator =, for instance in a declaration), or
  • implicit (parameters in a function signature, or within another destructuring, as you can indeed nest them).

Examples of positional destructuring:

const [first, runnerUp] = ['Alice', 'Bob', 'Claire', 'David']
first // 'Alice'
runnerUp // 'Bob'

const person = {
set fullName(text) {
// The leading semicolon is not technically necessary as we’re at
// the very beginning of the block, but Prettier likes to play it
// safe and also reduce diff footprints.
;[this.first, this.last] = text.split(/\s+/)
},
}

Exampled of named destructuring:

// Implicit, on the first argument passed to the function:
function TextField({ name, onChange, value }) {
// …
}

// Explicit, here on-the-fly in a declaration:
const { first, last } = person

Which means that…

Alright, let’s invert two variables a and b without breaking a sweat:

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

Voilà.

I’d like to say “it doesn’t get any shorter than this,” but some languages have advanced-enough parsers that they can avoid ambiguities and allow destructs without delimiters (e.g. Ruby would go: a, b = b, a 😍). But hey, no more temporary variable, and the intent is immediately clearer!

By the way, this is not at all limited to two values, you know! Let’s say you want to rotate values across a triplet. No worries:

// Again, Prettier insists on prefixing this with a semicolon so this
// code works *anywhere* despite no semis elsewhere.
;[a, b, c] = [b, c, a]

Big mood 🤗

Want to dive deeper?

Our trainings are amazeballs, be they in-room or remote online, multi-client or in-house just for your company!