14

Lets say I have this code:

const {x, y} = point;

Babel will turn this into:

var _point = point,
    x = _point.x,
    y = _point.y;

Which is fine, but what if point is undefined? Now I get an error:

"Cannot read property 'x' of undefined".

So how do I avoid this?

I want to do something like

const {x, y} = {} = point;

but that's a syntax error.

I can only see that this is an option:

const {x, y} = point || {};

Which babel transpiles to:

var _ref = point || {},
    x = _ref.x,
    y = _ref.y;

Here we're creating an object just to avoid an undefined error. This seems wasteful.

Is there some syntax I'm missing that would avoid this? Something that would transpile to something like this:

var x, y;
if (typeof point !== 'undefined') {
    x = point.x;
    y = point.y;
}
bignose
  • 30,281
  • 14
  • 77
  • 110
Jack Allan
  • 14,554
  • 11
  • 45
  • 57
  • 1
    I think this reiterative checking if the object is defined could be a waste of time. Probably you should check if the object is defined before destructuring it, isn't it? – dloeda Jul 03 '17 at 13:20
  • Yeah but putting a const in an if statement means that it's only available to code inside the if block, unless I change it to a var. – Jack Allan Jul 03 '17 at 13:24
  • 2
    If you're concerned about the creation of the object (which *really* is cheap), just use a predefined object. – Bergi Jul 03 '17 at 13:29
  • @Bergi that's a good idea – Jack Allan Jul 03 '17 at 13:30
  • 4
    Javascript is wasteful by nature, and the cases where || {} is going to make a practical difference are very very very rare. If you wanted to write the most efficient js possible, you might not want to use babel in the first place, but if you need that kind of performance then you are already triggering the poor users' cpu fans by using javascript at all -- and you would get better results through restructuring the performance critical parts in other ways. I'd say just optimize for readability in this case. – Jostein Jul 03 '17 at 13:37
  • 1
    `const x = point && point.x, y = point && point.y;` could be a verbose option. It does not create the intermediate empty object, but it does check `point` twice. But all this seems looking for an optimisation that becomes insignificant once you are actually going to do something with those coordinates (like drawing...). – trincot Jul 03 '17 at 16:48
  • `Here we're creating an object just to avoid an undefined error.` sure but due to the nature of short-circuiting for logical operators, the object creation only occurs when necessary, and as pointed out by others is extremely cheap anyway. – Patrick Roberts May 11 '18 at 05:13

3 Answers3

12

To handle undefined error in ES6 object destructuring, you can do something like following

const {x, y} = {...point};
console.log(x)      // undefined                  
console.log(y)      // undefined                  
Jitender
  • 7,593
  • 30
  • 104
  • 210
  • I knew I was being optimistic when I searched for a way to do this, but that's an awesome answer and does what I need. Thanks x100!! – mowwwalker Jul 22 '21 at 15:53
1

Let's assume when user can be a object or undefined

const user = { isManual: true }; // object
//const user = undefined // undefined

when you know that user can be undefined do two things, 1-Define destruct property default value. 2-use (user || {}) when user will undefined that'll use {}. So whenever user object will be undefined isManual will be false.

const { isManual = false } = user || {} 
console.log("isManual", isManual)
0

[…] what if point is undefined? Now I get an error: "Cannot read property 'x' of undefined"

So how do I avoid this?

If you want to write clear code, you can explicitly check that condition:

let { x, y };
if (typeof point === 'undefined') {
    x = y = undefined;
} else {
    { x, y } = point;
}
Community
  • 1
  • 1
bignose
  • 30,281
  • 14
  • 77
  • 110