15

I am trying to convert an object to a leaner version using destructuring.

My object includes a nested array which also contains objects, from this array I would only like a few fields.

I can do the nested object destructuring fine, and the array destructuring fine but not together?

My current try looks like this:

var data = {
    title: "title1",
    bar: "asdf",
    innerData: [
       {
        title: "inner-title1",
        foo: "asdf"
       },
       {
        title: "inner-title2",
        foo: "asdf"
       }
    ]
};

var { title, innerData: [ { title} ] } = data;

console.log(title);

for (var { title} of innerData) {
  console.log(title);
}

But get a message saying innerData is not defined.

The outcome I would like might be:

{
    title: "title1",
    innerData: [
       {
        title: "inner-title1"
       },
       {
        title: "inner-title2"
       }
    ]
};
Teemu
  • 22,918
  • 7
  • 53
  • 106
shenku
  • 11,969
  • 12
  • 64
  • 118
  • 2
    Only do `var { title, innerData } = data;` to get the `innerData` array in the variable – Bergi Sep 01 '16 at 04:08

3 Answers3

12

Your destructuring doesn't do what you think.

var { title, innerData: [ { title} ] } = data;

is (essentially) equivalent to

var title = data.title;
var title = data.innerData[0].title;

Destructuring pulls out individual values, it will not map through the array for you. You'll need to do that manually if that is what you want.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • I did spot that I thought perhaps there was a way that I could iterate them in one step. cheers. – shenku Sep 01 '16 at 04:10
12

You can adjust the variable name to an identifier other than defined innerData ; use .map() or JSON.stringify(), JSON.parse() to filter title property from innerData objects

var {title, titles = data.innerData.map(o => ({title:o.title}))} = data;

to maintain innerData variable name you can use array destructuring of object

var [title, innerData] = [data.title, data.innerData.map(o => ({title:o.title}))];

using JSON.stringify(), JSON.parse()

var [title, innerData] = JSON.parse(JSON.stringify([data.title, data.innerData], ["title"]));

Edit

If requirement is to create an array containing all title properties within data you can use JSON.stringify() with replacer array set to ["title"], JSON.parse(), spread element

var data = {
    title: "title1",
    bar: "asdf",
    innerData: [
       {
        title: "inner-title1",
        foo: "asdf"
       },
       {
        title: "inner-title2",
        foo: "asdf"
       }
    ]
};

var innerData = JSON.parse(JSON.stringify([data, ...data.innerData], ["title"]))
                                                                      
console.log(innerData);
guest271314
  • 1
  • 15
  • 104
  • 177
1

As per @loganfsmyth suggested, I will do it in two steps.

var { title } = data;

for (var { title } of data.innerData) {
  console.log( title );
}

Edit: my final solution to build a new json object from the old

const request = { innerData: [] };

({ title } = this.data);

for (const { title} of this.data.innerData) {
    request.innerData.push({
        title
    });
}
shenku
  • 11,969
  • 12
  • 64
  • 118
  • 1
    Note, `data` at Answer if different from `data` at Question; `foo` properties are not present at `data.innerData`. Is requirement to assign `title` to `data.title`, `innerData` as array of values corresponding to value of `title` of `data.innerData` without `foo` property? – guest271314 Sep 01 '16 at 06:52