我在插件/库中编写了一个小缓存函数。需要HTMLElement
并返回一个装饰器。
return function _cache(elem) {
if (elem.id === "") {
elem.id = PLUGIN_NAME + "_" + uid++;
}
if (cache[elem.id] === void 0) {
cache[elem.id] = _factory(elem);
}
return cache[elem.id];
}
这里我通过id
的{{1}}将一些昂贵的操作存储在缓存中。这是HTMLElement
查询,但它使用设置O(1)
并产生副作用的“不良做法”。
备选方案是elem.id
查找缓存
O(N)
但这意味着我的缓存昂贵的方法对return function _cache(elem) {
for (var i = 0, ii = cache.length; i++) {
var o = cache[i];
if (o.elem == elem) return o.data;
}
var ret = _factory(elem);
cache.push({ elem: elem, data: ret });
return ret;
}
没有任何副作用。
问题:
这种“副作用”是无辜的,是否值得为我的装饰师进行优化?
真实代码:
Gist of plugin template where I use this snippet
修改
我显然太累了,忘了HTMLElement
存在。这是应该如何实施的
data-foo
答案 0 :(得分:6)
不使用id
,而是使用data-x
- 这就是为其创建的内容。
id
有一个特定的含义,看到它自动生成是令人困惑的(即使记录正确,几乎从来没有。)你也冒着轻微覆盖的风险。
答案 1 :(得分:4)
这种“副作用”是无辜的
不,很清楚。是否可以与页面上的其他脚本进行良好的交互?不知道......这取决于它的用途以及你希望它与之结合的其他类型的脚本。你永远不能制作一个在与其他插件和脚本交互时不会失败的“插件”,但是通过将副作用保持在最低限度,你至少可以尝试将其最小化。
请注意,id
不是唯一标识符。虽然在一个特定时间文档中应该只有一个具有给定ID的元素,但是(a)可以使用相同的ID创建多个元素并按顺序插入到文档中(可能一个元素用相同的ID替换另一个元素),以及(b)人们仍然使用重复的ID,即使它是错的。这两种情况都会导致您的缓存收集旧的,不再使用的元素并且不恰当地返回它们。
遗憾的是,没有JavaScript函数来获取任意对象的标量/可散列唯一标识符;获得对象标识的唯一方法是===
- 与其他对象进行比较。
另一种常见的方法是向节点添加任意新属性(IE术语中的'expando'),具有随机化的真正唯一ID。标准版无法保证Expandos的正常运行,但它在所有浏览器中都可以使用,并且常用。
这就是jQuery如何唯一地识别元素,如果你正在为jQuery编写插件,你可以尝试利用它 - jQuery.expando
保存用于此目的的任意expando属性的名称。 。或者,保留在记录的功能集中,data()
可用于向元素添加您自己的元数据,包括您自己的另一个唯一ID。
Expandos确实有一些令人不快的副作用,包括意外地将它们视为IE< 9中的属性(它无法区分属性和属性),但是如果你使用jQuery,你可能没有任何东西输了。
值得为我的装饰师进行优化吗?
取决于您期望在页面上拥有多少。将每个项目与每个项目进行比较是O( n ²)操作;如果 n 很低,但是随着 n 的增长很快变得无法管理,那么可以容忍(并且可能更好地考虑副作用)。