Я получаю JSON-ответ от API, который я хочу подготовить и создать новый объект.

const things = [{
    "menu": {
      "id": "file",
      "value": "File",
      "popup": {
        "menuitem": [{
            "value": "3",
            "onclick": "CreateNewDoc()"
          },
          {
            "value": "5",
            "onclick": "OpenDoc()"
          },
          {
            "value": "8",
            "onclick": "CloseDoc()"
          }
        ]
      }
    }
  },
  {
    "menu": {
      "id": "image",
      "value": "Image",
      "popup": {
        "menuitem": [{
            "value": "New",
            "onclick": "CreateNewImage()"
          },
          {
            "value": "Open",
            "onclick": "OpenImage()"
          },
          {
            "value": "Close",
            "onclick": "CloseImage()"
          }
        ]
      }
    }
  }
];

Я знаю старый способ сделать это так:

const chs = [];
things.forEach((e) => {
    const i = {};
    i.Id = e.menu.id;
    i.Value = e.menu.value;
    i.PopupValue = e.menu.popup.menuitem[0].value;
    i.SomethingComputed = e.menu.popup.menuitem[0].value - e.menu.popup.menuitem[1];
    i.ShiftedUp = e.menu.popup.menuitem;
    chs.push(ch);
  });

Теперь я хочу сделать это с помощью ES6 и деструктуризации. но я не думаю, что взял это так далеко, как могу, потому что у меня: 1) все еще есть петля; 2) должны создать этот новый объект; и 3) нужны эти отдельные вычисляемые строки. Могу ли я получить это более компактным?

const chs = [];
things.forEach((e) => {
    const {
        Id: {id},
        Value: {value},
        PopupValue : {menu: {popup} },
    } = e;

    // computed 
    const someComputedValue = Value - PopupValue;

    // new object
    const ch = {
        Id,
        Value,
        SomeComputedValue
    }

    chs.push(ch);
});
1
VBAHole 1 Май 2019 в 22:40

4 ответа

Лучший ответ

Вы можете использовать map() вместо forEach(), поэтому вам не нужен шаг chs.push() в конце.

Вы можете поместить деструктурирование непосредственно в список аргументов, чтобы вам не понадобился шаг присваивания. Является ли это более удобным для чтения является дискуссионным.

Если вычисление для SomeComputedValue не слишком сложно, вы можете поместить его непосредственно в возвращаемый объект. Затем вы можете избавиться от этого присваивания и использовать сокращенную форму функции стрелки, которая просто возвращает значение.


const things = [{
    "menu": {
      "id": "file",
      "value": "File",
      "popup": {
        "menuitem": [{
            "value": "3",
            "onclick": "CreateNewDoc()"
          },
          {
            "value": "5",
            "onclick": "OpenDoc()"
          },
          {
            "value": "8",
            "onclick": "CloseDoc()"
          }
        ]
      }
    }
  },
  {},
  {
    "menu": {
      "id": "image",
      "value": "Image",
      "popup": {
        "menuitem": [{
            "value": "New",
            "onclick": "CreateNewImage()"
          },
          {
            "value": "Open",
            "onclick": "OpenImage()"
          },
          {
            "value": "Close",
            "onclick": "CloseImage()"
          }
        ]
      }
    }
  }
];

const chs = things.map(({
menu: {
    id: Id,
    value: Value,
    popup : PopupValue,
} = {id: "defaultID", value: "defaultValue", popup: "defaultPopup"}}) => ({
        Id,
        Value,
        SomeComputedValue: Value - PopupValue
    })
);

console.log(chs);
1
Barmar 2 Май 2019 в 19:07

Вы не можете избежать цикла, потому что things является массивом, поэтому вы должны выполнять его итерацию. Однако вы можете избежать создания нового объекта и добавления массива chs с помощью функции map, поскольку он по существу создает новый элемент для каждого элемента массива orignial и возвращает массив с недавно созданными элементами или объектами в вас. кейс. Таким образом, в этом случае функция map будет обрабатываться как зацикливанием, так и созданием нового объекта.

Кроме того, вы можете переместить деструктурирование в параметр обратного вызова функции map, и при возврате объекта можно выполнить вычисление:

const chs=things.map(({menu:{id,value,popup}}) => ({
        Id: id,
        Value: value,
        PopupValue : popup,
        SomeComputedValue: value+id

    }) 
);

Я протестировал описанную выше деструктуризацию, она работает для вашего массива things, как вы его предоставили.

1
Nabil Shahid 1 Май 2019 в 20:29

Неразрушающий путь на самом деле больше похож на этот:

const chs = things.map(e => ({
  Id: e.menu.id,
  Value: e.menu.value,
  PopupValue: e.menu.popup.menuitem[0].value,
  SomethingComputed: e.menu.popup.menuitem[0].value - e.menu.popup.menuitem[1],
  ShiftedUp: e.menu.popup.menuitem,
}));

И деструктурирование, или просто общая концепция разделения вещи на большее количество переменных, не должно быть всем или ничем:

const chs = things.map(({menu}) => {
  const {menuitem} = menu.popup;

  return {
    Id: menu.id,
    Value: menu.value,
    PopupValue: menuitem[0].value,
    SomethingComputed: menuitem[0].value - menuitem[1],
    ShiftedUp: menuitem,
  };
});
1
Ry- 1 Май 2019 в 19:58

Это не красиво, но это можно сделать с помощью деструктуризации. Вы можете создать такую функцию стрелки, которая разрушает каждый объект в массиве и возвращает новый объект. Затем используйте его как обратный вызов для {{X0} }

const things=[{menu:{id:"file",value:"File",popup:{menuitem:[{value:"3",onclick:"CreateNewDoc()"},{value:"5",onclick:"OpenDoc()"},{value:"8",onclick:"CloseDoc()"}]}}},{menu:{id:"image",value:"Image",popup:{menuitem:[{value:"New",onclick:"CreateNewImage()"},{value:"Open",onclick:"OpenImage()"},{value:"Close",onclick:"CloseImage()"}]}}}];

const callback = ({
  menu: {
    id: Id,
    value: Value,
    popup: {
      menuitem
    }
  }
}) => ({
  Id,
  Value,
  ShiftedUp: menuitem,
  PopupValue: menuitem[0].value,
  SomethingComputed: menuitem[0].value - menuitem[1].value
})

console.log(things.map(callback))

Вы можете даже уничтожить индексы массива menuitem, чтобы получить первые 2 value для разделения переменных следующим образом:

const callback = ({
  menu: {
    id: Id,
    value: Value,
    popup: {
      menuitem
    },
    popup: {
      menuitem: [
        { value: Value0 },
        { value: Value1 }
      ]
    }
  }
}) => ({
  Id,
  Value,
  ShiftedUp: menuitem,
  PopupValue: Value0,
  SomethingComputed: Value0 - Value1
})
1
adiga 2 Май 2019 в 07:17