3

I have a problem, or more some weird situation. I am using https://es6console.com.

I want to use destructuring and assign properties to already declared variables. It looks like that there is a problem in where I declare object. Please open https://es6console.com/jm6e72c7/ and click Transform to ES5. There is a weird behaviour where I declare object after variables.

// not working
let ip, port;

let config = {
    ip: 'ip',
    port: 'port'
}

({ip, port} = config)

console.log(ip);

//working
let obj = {
    name: 'name',
    age: 'age'
}

let name, age;

({name, age} = obj)

console.log(name);
zamf123
  • 33
  • 4

3 Answers3

3

This is one of those situations where the semi-colon is mandatory:

let ip, port;

let config = {
 ip: 'ip',
 port: 'port'
};  //< --- you need the ;

({ip, port} = config)

console.log(ip);

Otherwise javascript will interpret the code as:

let config = {ip: 'ip',port: 'port'}() which is a type error because it tries to call a function.
Mark
  • 90,562
  • 7
  • 108
  • 148
  • Why is it necessary? Cuz of the brackets just after it that makes it ambiguous? – Alexandre Elshobokshy Sep 17 '18 at 14:54
  • It isn't mandatory. It's just slightly ambiguous without it. It'll work fine. – lonesomeday Sep 17 '18 at 14:56
  • 1
    @IslamElshobokshy without the semicolon, the set of parentheses after config look to the parser like you're trying to call a function. Try pasting the code into https://astexplorer.net/ and you'll see it thinks the parens form a CallExpression – Nicholas Tower Sep 17 '18 at 14:58
  • @lonesomeday this throws an error without the semicolon. – Mark Sep 17 '18 at 14:58
  • 2
    @MarkMeyer In the browser. The transpiler is fine with it. Which may be an error with the transpiler, but arguably not with code that targets it. – lonesomeday Sep 17 '18 at 14:59
  • Okay, @lonesomeday, that's fair enough, but the transpired code will still throw an error. So I would say the semicolon is still mandatory -- at least in the spirit of this question. – Mark Sep 17 '18 at 15:02
3

First off, they both work. You have two different ways to compile ES6 code to ES5:

({ip, port} = config)
// converted to
((_config = config, ip = _config.ip, port = _config.port, _config));

// and

({name, age} = obj)
// converted to
name = obj.name;
age = obj.age;

The result, in both cases, is that the variables are set to the appropriate values from the object.

The difference is that the transpiler thinks the return value of the assignment operation might be important in the first case, but won't be in the second case. So in the first case, you'll see _config at the end as the return value. It isn't needed, actually, but the transpiler is defensive -- it will do its best to make sure the functionality is exactly the same.

As to why it thinks that you might want the return value in the first case, it's because of the missing semi-colon after the declaration of the config object.

With the semi-colon added, it works as expected:

let config = {
    ip: 'ip',
    port: 'port'
};

({ip, port} = config)

Working example

lonesomeday
  • 233,373
  • 50
  • 316
  • 318
0

the problem is a missing semicolon.

let ip, port;

let config = {
 ip: 'ip',
 port: 'port'
}

({ip, port} = config)//this is being evaluated as part of the let config declaration...

console.log(ip);
console.log('------------------------------');

let obj = {
 name: 'name',
 age: 'age'
}

let name, age;

({name, age} = obj)

console.log(name);

needs to be

let ip, port;

let config = {
 ip: 'ip',
 port: 'port'
};//added semicolon here

({ip, port} = config);//not needed here, but good to have

console.log(ip);
console.log('------------------------------');

let obj = {
 name: 'name',
 age: 'age'
}

let name, age;

({name, age} = obj)

console.log(name);

you'll notice that, even when run as es6, you get a destructuring error on the first snippet. this is because the interpreter is reading the statement as

let ip, port;
let config = {ip:'ip',port:'port'}({ip, port} = config)
dgeare
  • 2,618
  • 5
  • 18
  • 28