人们是否曾使用基于DOM的数据存储/检索而不是数组或对象来使索引更简单?
考虑下面的代码段。要将颜色更新为棕色,无论name = Bob在Javascript中需要两个循环:一个用于团队,一个用于玩家。然后进行比较以在进行颜色更改之前检查name = Bob。
var obj = {"team1": {
"player1": {
"name": "bob",
"color": "red",
},
"player2": {
"name": "george",
"color": "blue",
},
},
"team2": {
"player1": {
"name": "bob",
"color": "orange",
},
"player2": {
"name": "george",
"color": "green",
},
}};
for (var i in obj)
for (var j in obj[i])
if (obj[i][j]["name"] == 'bob')
obj[i][j]["color"] = 'brown';
console.log(obj); // color changed to brown for the two bobs

但是如果数据存储在DOM中,则在表格单元格"数据"例如,使用一行jQuery更新name = bob的颜色更容易:
$("td[data-name='bob']").data("color", "brown");
我的javascript对象有大约1000个团队,每个团队有4-5个玩家。为每种颜色变化循环整个事情似乎需要很多开销。而jQuery似乎能够将整个DOM保存在内存中(真正的陈述?)并直接切换到正确的单元格并进行颜色更改。
或者,为了做出改变,jQuery实际上必须在幕后执行两个循环(或类似的性能成本)?
答案 0 :(得分:2)
执行$("td[data-name='bob']")
时,必须迭代DOM。与此相比,数据对象的循环非常轻。与在对象结构中执行简单更新相比,更新DOM中的属性的时间要长得多。因此,您需要为看起来容易的事情付出代价。
两个循环确实没有问题:重要的是你需要访问的条目数。
如果您经常需要根据播放器名称进行更新,那么您可以考虑甚至添加类似索引的数据结构,以便通过名称更快地访问:
const obj = {"team1": {"player1": {"name": "bob","color": "red"},"player2": {"name": "george","color": "blue"}},"team2": {"player1": {"name": "bob","color": "orange"},"player2": {"name": "george","color": "green"}}};
// Create a structure keyed by name
const byName = {};
for (const [team, players] of Object.entries(obj)) {
for (const [playerId, player] of Object.entries(players)) {
byName[player.name] =
(byName[player.name] || []).concat({team, playerId, player});
}
}
function updateColorForName(name, color) {
for (const info of byName[name]) {
info.player.color = color;
}
}
// Sample call:
updateColorForName("bob", "brown");
// Show update:
console.log(obj);

.as-console-wrapper { max-height: 100% !important; top: 0; }

要进一步使用ES6电源,请使用更合适的Map
:
const obj = {"team1": {"player1": {"name": "bob","color": "red"},"player2": {"name": "george","color": "blue"}},"team2": {"player1": {"name": "bob","color": "orange"},"player2": {"name": "george","color": "green"}}};
// Create a Map keyed by name
const byName = new Map();
for (const [team, players] of Object.entries(obj)) {
for (const [playerId, player] of Object.entries(players)) {
byName.set(player.name,
(byName.get(player.name) || []).concat({team, playerId, player}));
}
}
function updateColorForName(name, color) {
for (const info of byName.get(name)) {
info.player.color = color;
}
}
// Sample call:
updateColorForName("bob", "brown");
// Show update:
console.log(obj);

.as-console-wrapper { max-height: 100% !important; top: 0; }