0

I have a block of code:

const {address, cityDistrict, city, country} = data;

const obj = {
  location: {address, cityDistrict, city, country}
};

But can I write this one shorted? I tried this one, but it's wrong:

const obj = {
  location: {address, cityDistrict, city, country} = data
};

Is it possible?

rel1x
  • 2,351
  • 4
  • 34
  • 62

3 Answers3

4

This actually does work (in Chrome at least, in Babel too if you wrap the assignment in parenthesis), but the two pieces of code are not equivalent.

The second piece of code simply assigns data to the location property and creates 4 new variables in scope called address, cityDistrict, etc.

For example:

const data = {
  address: "Address",
  cityDistrict: "District",
  city: "City",
  country: "Country"
}

const obj = {
  location: ({address, cityDistrict, city, country} = data)
};
console.log(obj);

Looks like it logs the correct data, but what is actually printing is data, not new object. So if we do something like this:

const obj = {
  location: ({address, cityDistrict, city, country} = data)
};

data.address = "Test"

console.log(obj); // location.Address = Test

You'd get unexpected data. As a side effect of that, you'd also get 4 new variables in scope:

const obj = {
  location: ({address, cityDistrict, city, country} = data)
};

console.log(address, cityDistrict, city, country); // All defined

What you really want to do is to use Object.assign to create a new instance of an object:

const obj = {
    location: Object.assign({}, data);
}
CodingIntrigue
  • 75,930
  • 30
  • 170
  • 176
  • Hi! Thank you for the answer, but I can't do `Object.assign({}, data)` because I have lots of unused data inside `data` – rel1x Oct 17 '16 at 14:45
  • @rel1x I understand. I usually use [lodash.pick](https://www.npmjs.com/package/lodash.pick) or [this native implementation](http://stackoverflow.com/questions/25553910/one-liner-to-take-some-properties-from-object-in-es-6) – CodingIntrigue Oct 17 '16 at 14:48
0

This will not work using the es2015 preset, but will work using es2016.

Trying this in https://babeljs.io/repl illustrates this.

Updated

The answer from CodingIntrigue shows why this one does not work.

I also think what you want is currently not achievable with a destructuring one-liner. You'd better stick to your first intent unless you really don't want to have some variables assignments, and in such case you'd likely use an IIFE to filter keys.

As zeroflagl said, you can do it using spread properties if you use ES proposal stage 3.

const data = {
  address: 'address',
  cityDistrict: 'district',
  city: 'city',
  country: 'country'
}
const { address, cityDistrict, city, country } = data;

const obj = {
  location: {...data}
};

console.log(obj)

/* logs Object {
  "location": Object {
    "address": "address",
    "city": "city",
    "cityDistrict": "district",
    "country": "country"
  }
}
*/
Community
  • 1
  • 1
dashdashzako
  • 1,268
  • 15
  • 24
  • I'm not sure this is expected behavior - just a side effect of different parsing techniques between the two presets' plugins maybe? – CodingIntrigue Oct 17 '16 at 10:29
  • You're right @CodingIntrigue, and your `You'd get unexpected data. As a side effect of that, you'd also get 4 new variables in scope` says it all. I think the best one-liner we can do would be an immediately invoked function expression using `data` as a parameter to filter the keys. But the result is less understandable than the original code. – dashdashzako Oct 17 '16 at 11:21
  • 1
    _"what you want is not achievable with a destructuring one-liner."_ If data does not contain additional properties: `location: {...data}`. Stage 3 proposal. – a better oliver Oct 17 '16 at 12:14
  • Nice addition @zeroflagL, I wasn't aware of this. It's worth mentioning [Stage 3 proposal] implementation still does not work on Babel REPL. – dashdashzako Oct 17 '16 at 12:45
  • It works. I successfully tested it. – a better oliver Oct 17 '16 at 12:47
  • I can't edit my comment above, but the [rest properties](https://github.com/sebmarkbage/ecmascript-rest-spread#rest-properties) example won't work with the repl. Spread properties will work though. – dashdashzako Oct 17 '16 at 12:54
  • Good to know. Thanks for the update. – a better oliver Oct 17 '16 at 13:16
0

If you want to copy data you can use it:

const obj = {location: Object.assign({}, data)}

Or you also can use next code, but changing obj.location can change data:

const obj = {location: data}
gwer
  • 614
  • 3
  • 5