Javascript деструктура с вычисленными значениями, сдвигом уровня и созданием нового объекта - PullRequest
1 голос
/ 01 мая 2019

Я получаю ответ 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);
});

Ответы [ 4 ]

1 голос
/ 01 мая 2019

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

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

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

    }) 
);

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

1 голос
/ 01 мая 2019

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

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 голос
/ 01 мая 2019

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

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 s для разделения переменных, например:

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 голос
/ 01 мая 2019

Вы можете использовать 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);
...