我有以下场景:我有一个对象数组(TreeItems),其中可能包含嵌套数组。我还有另一个带有索引的数组。现在我想使用索引数组更改 TreeItems 数组以访问特定的树项目,并且根据是否存在名为“items”的嵌套数组,我想附加现有数组或添加新数组。最重要的是,我想摆脱邪恶的评估。
因此,在我的示例中,我尝试在 TreeItems[4][0][0] 添加一个新条目,但括号中的索引应该从索引数组中动态添加,但我不太清楚如何执行此操作。
我当然已经搜索过并找到了这个,但它对我来说不太有用。
任何帮助将不胜感激。
const TreeItems = [
{ text: "Lvl 0", items: [{ text: "Lvl 0-0" }, { text: "Lvl 0-1" }] },
{ text: "Lvl 1" },
{ text: "Lvl 2", items: [{ text: "Lvl 2-0" }, { text: "Lvl 2-1" }] },
{ text: "Lvl 3" },
{
text: "Lvl 4",
items: [
{
text: "Lvl 4-0",
items: [
{
text: "Lvl 4-0-0",
items: [{ text: "Lvl 4-0-0-0" }, { text: "Lvl 4-0-0-1" }, { text: "Lvl 4-0-0-2" }],
},
{ text: "Lvl 4-0-1" },
{ text: "Lvl 4-0-2" },
],
},
],
},
];
const indexes = [4,0,0];
let comString = '';
for(let i = 0; i < indexes.length; i++) {
if(i === 0) {
comString = "TreeItems[" + indexes[i] + "]";
} else {
comString += ".items[" + indexes[i] + "]";
}
}
if(eval(comString).items !== undefined) {
eval(comString).items.push({"text": "Test-item-appended"});
} else {
eval(comString).items = [{"text": "Test-items-added"}]
}
console.log(comString);
console.log(eval(comString).items);
console.log(TreeItems);
您不必使用
eval
或任何类型的动态代码生成来执行此操作。事实上,除非您明确希望执行一段外部 JavaScript 代码,否则不存在需要使用 eval
的编程问题。
如果您想使用索引数组作为路径来访问
TreeItems
的嵌套子级,您可以创建一个变量,用于将子级存储在深度 n
处,从 0 开始,然后用位于 的子级重复覆盖它深度 n + 1
,直到您考虑了路径中的所有索引:
function getTreeItem(path) {
// get first child, whose index is at path[0]
let currentChild = TreeItems[path[0]];
// for indices at path[1] and further, overwrite currentChild with the next child
for (let i = 1; i < path.length; i++)
currentChild = currentChild.items[path[i]];
return currentChild;
}
请注意,使用 for 循环和 let 语句有点冗长,并且违背了现代 JavaScript 的编码风格。执行此操作的正确方法是使用 Array.prototype.reduce,如您找到的答案中所建议的。最初的问题是关于数组的数组,而在本例中,您正在访问具有名为
items
的属性的对象数组,并且您的函数必须考虑到这一点。
以下代码在功能上等同于上面的代码:
function getTreeItem(path) {
return path.reduce(
(currentChild, currentPathIndex, depth) => {
// if currentPathIndex is path[0], set currentChild to the currentPathIndex-th child of TreeItems
if (depth == 0)
return TreeItems[currentPathIndex];
// otherwise, set currentChild to the currentPathIndex-th child of currentChild.items
return currentChild.items[currentPathIndex];
},
// let the initial currentChild be null and the initial depth be 0
null
);
}
在 MDN 上了解有关 Array.prototype.reduce 的更多信息。
一旦获得了对父节点的引用,您就可以按照问题中提出的完全相同的方式向其添加项目:
function addTreeItem(parentPath, text) {
const parent = getTreeItem(parentPath);
if (parent.items)
parent.items.push({text})
else
parent.items = [{text}];
}
addTreeItem([4, 0, 0, 0], "added item");
addTreeItem([4, 0, 0, 0], "appended item");