将element.id设置为副作用不好的做法?

时间:2011-06-07 22:02:06

标签: javascript jquery dom

我在插件/库中编写了一个小缓存函数。需要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

2 个答案:

答案 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 的增长很快变得无法管理,那么可以容忍(并且可能更好地考虑副作用)。