人们是否曾经使用基于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中,例如存储在表单元格" data“属性中,那么用一行name=bob更新颜色就更容易了:
$("td[data-name='bob']").data("color", "brown");我的javascript对象大约有1000个队,每个队有4-5名队员.为每一种颜色的变化循环整个过程似乎需要很大的开销。而jQuery似乎能够在内存中保存整个DOM (真语句?)直接切到右边的细胞,然后改变颜色。
或者jQuery实际上必须在幕后执行两个循环(或类似的性能成本)才能进行更改?
发布于 2018-02-11 08:29:20
在执行$("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; }
https://stackoverflow.com/questions/48729489
复制相似问题