Celsius' Notes
Hire me as a freelancer for your mobile (iOS native, cross-platform with React Native), web and backend software needs.
Go to portfolio/resumé
3 min read

How to destructure a JavaScript object without a declaration.

This is how you destructure a JS object:

const book = {
    author: "Bobby B.",
    title: "Ladida"
}
const {author, title} = book;
console.log(author) // Bobby B.
console.log(title) // Ladida

How not to do it

However, sometimes you might need to destructure an object without declaring the identifiers on the left hand side as new variables, for instance, when those variables exist in the same scope and you can't redeclare the variables.

You might try to do something like this, which will give you a SyntaxError, as author and title have already been declared in the same scope:

let author;
let title;

const book = {
    author: "Bobby B.",
    title: "Ladida"
};

const {author, title} = book;

Since that didn't work, you might try something like in the following snippet. If you do, you will be met with a: "SyntaxError: Unexpected token =". This is because opening braces { at the beginning of a statement are interpreted as a block in JavaScript. And blocks cannot be assigned to.

let author;
let title;

const book = {
    author: "Bobby B.",
    title: "Ladida"
};

{author, title} = book;

Shadowing inside loops

Another example is when you loop through an array of items want to break the loop as soon as you encounter an item that holds a certain value.

Consider the following snippet. We have an array of books, consisting of an author and a title. We want to loop through it and assign the author and the title to the author and title variables that are declared before the loop, so that we can access those variables after the loop.

const books = [{}, {}, {}, {} ,{}, {author: "Bobby. B", title: "Ladida"}, {}, {}, {}, {} ,{}];

let author;
let title;

for(let book of books ){
    // destructure author and title out of book and if author is Bobby B. then break the loop.
}

Since the author and the title variables are declared outside of the for-of loop, we can destructure them inside the loop by declaring new author and title variables with the const or the let keyword and thus shadowing the variables outside of the loop.

This is not quite what we want, however. Since we declared these two variables inside the loop now, we won't be able to access them after the loop.
When logging the variables we get undefined for both of them, as the destructured variables, declared inside the loop, have gone out of scope once the loop has finished.

Note, that if you used var to declare the destructured variables inside the loop you would once again get a "SyntaxError: Identifier 'author' has already been declared". This is because var variables are function level scoped in JavaScript, whereas const and let variables are block scoped.

Don't use var!

const books = [{}, {}, {}, {} ,{}, {author: "Bobby. B", title: "Ladida"}, {}, {}, {}, {} ,{}];

let author;
let title;

for(let book of books ){
    const {author, title} = book;
    if(author === "Bobby. B"){
        break;
    }
}
console.log(author) // undefined
console.log(title) // undefined

The right way to do it

As mentioned above, when braces { appear as the beginning of a statement, they are interpreted as a block. When braces appear at later point in a statement, such as when beginning the statement with constlet or var (don't do it!), they are interpreted as an object.
So all we have to do is make it so that the braces do not appear first in the statement, while also not using constlet or var (seriously, don't).

How?
Wrap the entire line where the destructuring happens in parentheses ().

For our first code snippet we will get the following:

let author;
let title;

const book = {
    author: "Bobby B.",
    title: "Ladida"
};

({author, title} = book);

And this is what our second snippet looks like after wrapping the desctructuring line in parentheses:

const books = [{}, {}, {}, {} ,{}, {author: "Bobby. B", title: "Ladida"}, {}, {}, {}, {} ,{}];

let author;
let title;

for(let book of books ){
    ({author, title} = book);
    if(author === "Bobby. B"){
        break;
    }
}
console.log(author) // undefined
console.log(title) // undefined

When wrapping the entire line in parentheses, make sure to end the previous line with a semicolon. Otherwise, it might trigger a function invocation!