深入了解多嵌套数组语法糖
Drill down into multi-nested arrays syntactic sugar
当我需要深入研究数据结构时,我经常发现自己遵循这种模式,尤其是在我的 Redux reducer 中:
state.items = state.items.map((item) => {
item.subItems = item.subItems.map((subItem) => {
subItem.bottomItems = subItem.bottomItems.map((bottomItem) => {
// do something with bottomItem...
bottomItem.foo = 'bar';
return bottomItem;
});
return subItem;
});
return item;
});
为了达到 bottomItems
水平,这似乎有很多样板文件。
ES6 或 ES7 是否提供了一些语法糖来缓解这种模式?
我应该提到的第一件事是你那里的代码修改了原始状态。要维护 redux 的 state immutability principle,您只想 return 个新对象,而不是沿途修改现有对象。
就更简单的语法而言,如果您使用 arrow functions and object spread,这种模式还不错:
return {
items: state.items.map(item => ({
...item,
subItems: item.subItems.map(subItem => ({
...subItem,
bottomItems: subItem.bottomItems.map(bottomItem => ({
...bottomItem,
foo: 'bar' // update foo to 'bar' for every bottomItem in every subItem in every item
})
})
})
}
请注意,对象传播还不是该语言的一部分,它目前是第 3 阶段提案,很可能会成为下一个 ECMAScript 版本之一的一部分。因此,您必须使用 Babel 之类的工具对其进行转换才能在当今的浏览器中工作。
如果您不希望这样做并希望今天本地可用的功能,您可以改用 Object.assign:
return {
items: state.items.map(item => Object.assign({}, item, {
subItems: item.subItems.map(subItem => Object.assign({}, subItem, {
bottomItems: subItem.bottomItems.map(bottomItem => Object.assign({}, bottomItem, {
foo: 'bar' // update foo to 'bar' for every bottomItem in every subItem in every item
})
})
})
}
既然你想要一个更简洁、更易读的语法,我建议选项 1 :)
是的,嵌套的不可变更新可能很痛苦(正如我在 Redux 文档的 Structuring Reducers - Immutable Update Patterns 部分中提到的)。
您可能想研究使用其中的许多不可变更新实用程序库。这些库提供了多种语法和抽象来进行更简单的嵌套不可变更新。一些使用字符串键路径,另一些使用嵌套对象定义。一个典型的例子可能是 someLib.set(["items", "subItems", "bottomItems", 0, "someField"], someValue)
.
有关可用库的列表,请参阅 Immutable Data#Immutable Update Utilities section of my Redux addons catalog。
当我需要深入研究数据结构时,我经常发现自己遵循这种模式,尤其是在我的 Redux reducer 中:
state.items = state.items.map((item) => {
item.subItems = item.subItems.map((subItem) => {
subItem.bottomItems = subItem.bottomItems.map((bottomItem) => {
// do something with bottomItem...
bottomItem.foo = 'bar';
return bottomItem;
});
return subItem;
});
return item;
});
为了达到 bottomItems
水平,这似乎有很多样板文件。
ES6 或 ES7 是否提供了一些语法糖来缓解这种模式?
我应该提到的第一件事是你那里的代码修改了原始状态。要维护 redux 的 state immutability principle,您只想 return 个新对象,而不是沿途修改现有对象。
就更简单的语法而言,如果您使用 arrow functions and object spread,这种模式还不错:
return {
items: state.items.map(item => ({
...item,
subItems: item.subItems.map(subItem => ({
...subItem,
bottomItems: subItem.bottomItems.map(bottomItem => ({
...bottomItem,
foo: 'bar' // update foo to 'bar' for every bottomItem in every subItem in every item
})
})
})
}
请注意,对象传播还不是该语言的一部分,它目前是第 3 阶段提案,很可能会成为下一个 ECMAScript 版本之一的一部分。因此,您必须使用 Babel 之类的工具对其进行转换才能在当今的浏览器中工作。
如果您不希望这样做并希望今天本地可用的功能,您可以改用 Object.assign:
return {
items: state.items.map(item => Object.assign({}, item, {
subItems: item.subItems.map(subItem => Object.assign({}, subItem, {
bottomItems: subItem.bottomItems.map(bottomItem => Object.assign({}, bottomItem, {
foo: 'bar' // update foo to 'bar' for every bottomItem in every subItem in every item
})
})
})
}
既然你想要一个更简洁、更易读的语法,我建议选项 1 :)
是的,嵌套的不可变更新可能很痛苦(正如我在 Redux 文档的 Structuring Reducers - Immutable Update Patterns 部分中提到的)。
您可能想研究使用其中的许多不可变更新实用程序库。这些库提供了多种语法和抽象来进行更简单的嵌套不可变更新。一些使用字符串键路径,另一些使用嵌套对象定义。一个典型的例子可能是 someLib.set(["items", "subItems", "bottomItems", 0, "someField"], someValue)
.
有关可用库的列表,请参阅 Immutable Data#Immutable Update Utilities section of my Redux addons catalog。