Javascript 使用计算值、电平转换和新对象创建进行解构
Javascript destructure with computed values, level shifting and new object creation
我从 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);
});
您可以使用 map()
而不是 forEach()
,因此您不需要最后的 chs.push()
步骤。
你可以直接将解构放在参数列表中,这样你就不需要赋值步骤了。这是否更具可读性是有争议的。
如果SomeComputedValue
的计算不是太复杂,可以直接放在返回的对象中。然后你可以摆脱那个赋值,你可以使用 shorthand 形式的箭头函数,它只是 returns 一个值。
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);
非解构方式其实更像这样:
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,
};
});
这不是很漂亮,但是可以使用解构来做到这一点。您可以像这样创建一个箭头函数,它会解构数组中的每个对象并 returns 一个新对象。然后将其用作 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
来分隔变量,如下所示:
const callback = ({
menu: {
id: Id,
value: Value,
popup: {
menuitem
},
popup: {
menuitem: [
{ value: Value0 },
{ value: Value1 }
]
}
}
}) => ({
Id,
Value,
ShiftedUp: menuitem,
PopupValue: Value0,
SomethingComputed: Value0 - Value1
})
你无法避免循环,因为 things
是一个数组,所以你必须迭代它。但是,您可以避免使用 map
函数创建新对象并推入 chs
数组,因为它实质上为原始数组的每个元素和 returns 具有新创建元素的数组创建了一个新元素或您的情况下的对象。所以在这种情况下,基本上循环和新对象的创建都将由 map
函数处理。
另外,你可以将解构移动到map函数的回调参数中,在返回对象的同时进行计算:
const chs=things.map(({menu:{id,value,popup}}) => ({
Id: id,
Value: value,
PopupValue : popup,
SomeComputedValue: value+id
})
);
我已经测试了上面的解构,它适用于你提供的 things
数组。
我从 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);
});
您可以使用 map()
而不是 forEach()
,因此您不需要最后的 chs.push()
步骤。
你可以直接将解构放在参数列表中,这样你就不需要赋值步骤了。这是否更具可读性是有争议的。
如果SomeComputedValue
的计算不是太复杂,可以直接放在返回的对象中。然后你可以摆脱那个赋值,你可以使用 shorthand 形式的箭头函数,它只是 returns 一个值。
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);
非解构方式其实更像这样:
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,
};
});
这不是很漂亮,但是可以使用解构来做到这一点。您可以像这样创建一个箭头函数,它会解构数组中的每个对象并 returns 一个新对象。然后将其用作 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
来分隔变量,如下所示:
const callback = ({
menu: {
id: Id,
value: Value,
popup: {
menuitem
},
popup: {
menuitem: [
{ value: Value0 },
{ value: Value1 }
]
}
}
}) => ({
Id,
Value,
ShiftedUp: menuitem,
PopupValue: Value0,
SomethingComputed: Value0 - Value1
})
你无法避免循环,因为 things
是一个数组,所以你必须迭代它。但是,您可以避免使用 map
函数创建新对象并推入 chs
数组,因为它实质上为原始数组的每个元素和 returns 具有新创建元素的数组创建了一个新元素或您的情况下的对象。所以在这种情况下,基本上循环和新对象的创建都将由 map
函数处理。
另外,你可以将解构移动到map函数的回调参数中,在返回对象的同时进行计算:
const chs=things.map(({menu:{id,value,popup}}) => ({
Id: id,
Value: value,
PopupValue : popup,
SomeComputedValue: value+id
})
);
我已经测试了上面的解构,它适用于你提供的 things
数组。