Did you know you can time travel with variable assignment in JavaScript? Here's some silly JavaScript trivia for your day.
Multiple Assignment
You probably know about multiple assignment in JavaScript. Hopefully you know that it's not recommended because it can be hard to see when it's not in a tiny example and is a good way to introduce bugs if you assign one object to two variables.
let a, b;
// Set two things at once
a = b = 1;
a; // 1
b; // 1
If you do use this, be careful! It's possible to accidentally create a variable in the global scope.
// a is local, b is global unless declared beforehand!
const a = b = 1;
a; // 1
globalThis.b; // 1
But multiple assignment is possible, and it works with destructuring, too! Multiple assignment returns the variable, so each destructuring above gets the full array.
let a, b;
// 🔎 Looks pretty strange
[, ...a] = [b] = [ 0, 1, 2 ];
a; // [ 1, 2 ]
b; // 0
But what about the time travel? We're getting there...
Default Values
With destructuring you can also set default values.
const [ a, b, c, d = '🍊' ] = [ 0, 1, 2 ];
a; // 0
b; // 1
c; // 2
d; // '🍊'
And you can do this with multiple assignment.
let a, b;
// Defaults for missing values
[a = '🍇'] = [b = '🍐'] = [];
a; // '🍇'
b; // '🍐'
But what about time travel?!
Time Travel
Let's see it in action, first.
let first, second, vegetable, fruit;
// 🪄⏱️ Time Travel!
[ first, vegetable = fruit ] = [ second, fruit = '🍅' ] = ['🥦'];
first; // '🥦'
second; // '🥦'
vegetable; // '🍅'
fruit; // '🍅'
vegetable
shows up first on the line, but manages to access the value assigned to fruit
which is assigned later in the line!
Time travel!
What's Going On Here?
Well, of course it's not really time travel. What's happening here is the difference between reading and interpretation. We read this code left-to-right, but JavaScript assignment happens right-to-left. The "second" destructuring in reading order happens first. If we break this into code is roughly equivalent.
let first, second, vegetable, fruit;
// Multiple assignment passes the original value.
// Simulate that with an interim assignmentResult inside a block.
// This block scope makes the temporary variable inaccessible.
{
const assignmentResult = [ second, fruit = '🍅' ] = ['🥦'];
// fruit was assigned a value by the time this code is run
[ first, vegetable = fruit ] = assignmentResult;
}
first; // '🥦'
second; // '🥦'
vegetable; // '🍅'
fruit; // '🍅'
Conclusion
So, not exactly time travel but a great way to demonstrate some of the unexpected functionality in JavaScript. Because the TC39 working group focuses on maintaining compatibility of older code, some mixing of old and new coding styles and standards can create confusing code.
Hopefully you never encounter real code like this!
Top comments (0)