【问题标题】:Javascript destructure with computed values, level shifting and new object creation带有计算值、电平转换和新对象创建的 Javascript 解构
【发布时间】:2019-05-01 19:40:42
【问题描述】:

我从一个我想要修饰并创建一个新对象的 api 获得一个 json 响应。

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);
});

【问题讨论】:

  • 您可以通过使用Array#map 而不是Array#forEach 来提高可读性。解构可能会帮助您使其更紧凑,但在这种情况下不会使其更具可读性。
  • 旧方式干净、易读,而且可能比使用解构更快。
  • @adiga 不,解构本身并不慢。
  • @adiga 临时变量通常不会影响速度,解释器无论如何都必须将中间结果存储在某个地方——并且在编译时,相同的数据流图(有或没有附加变量)通常会导致相同的结果注册分配。
  • @adiga 想一想,第一个 sn-p 可能比解构为临时变量还要慢,因为(昂贵的)属性访问必须重复多次。优化器必须竭尽全力推断它可以安全地将它们折叠成每个属性一个,证明它们没有副作用(例如,某些对象的 getter 属性)。

标签: javascript ecmascript-6 destructuring


【解决方案1】:

您可以使用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);

【讨论】:

  • 您从 OP 复制了错误的解构。请问你能解决这个问题吗?
  • 我认为我从第二个代码 sn-p 中正确复制了它。
  • 是的,你复制了它,但它不起作用。查看正确版本的其他答案(这相当于 OP 在他的第一个 sn-p 中所做的)
  • 我认为他的版本有效,而他只是在寻找一种更优雅的方式来编写它(尽管现在这表明Code Review 可能会更好)。
  • PopupValue: {menu: {popup} = {popup: defaultValue}}
【解决方案2】:

非解构的方式其实更像这样:

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,
  };
});

【讨论】:

    【解决方案3】:

    您无法避免循环,因为things 是一个数组,因此您必须对其进行迭代。但是,您可以避免使用map 函数创建新对象并推入chs 数组,因为它本质上为原始数组的每个元素创建一个新元素,并在您的情况下返回包含新创建的元素或对象的数组。因此,在这种情况下,基本上循环和新对象的创建都将由 map 函数处理。

    另外,你可以将解构移动到map函数的回调参数中,并且可以在返回对象的同时进行计算:

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

    我已经测试了上述解构,它适用于您提供的 things 数组。

    【讨论】:

      【解决方案4】:

      这并不漂亮,但可以使用解构来做到这一点。您可以创建一个像这样的箭头函数,它解构数组中的每个对象并返回一个新对象。然后将其用作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 个 values 来分隔变量,如下所示:

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

      【讨论】:

        猜你喜欢
        • 2019-01-06
        • 2021-04-06
        • 1970-01-01
        • 1970-01-01
        • 2019-08-11
        • 2021-11-07
        • 2023-02-02
        • 2017-12-13
        • 2015-09-24
        相关资源
        最近更新 更多