将element.id设置为副作用是一种糟糕的做法

Is setting element.id as a side effect bad practice?

本文关键字:一种 设置 id element 副作用      更新时间:2023-09-26

我正在插件/库中编写一个小的缓存函数。它获取一个HTMLElement并返回一个Decorator。

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];
}

在这里,我通过HTMLElementid将一些昂贵的操作存储在高速缓存中。这是一个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;
}

但这意味着我缓存的昂贵方法对HTMLElement没有任何副作用。

问题:

这种"副作用"是无辜的吗?值得对我的装饰器进行优化吗?

真实代码:

Gist的插件模板,我在那里使用这个片段

编辑:

我显然太累了,忘记了data-foo的存在。以下是应该如何实现

var attr = "data-" + PLUGIN_NAME + "-cache";
return function _cache(elem) {
    var val = elem.getAttribute(attr);
    if (val === null || val === "") {
        val = PLUGIN_NAME +  "_" + uid++;
        elem.setAttribute(attr, val);
    }
    if (cache[val] === undefined) {
        cache[val] = _factory(elem);
    }
    return cache[val];
}

不要使用id,而是使用data-x——这就是它的创建目的。

id有一个特定的含义,看到它自动生成是令人困惑的(即使有正确的文档记录,这几乎从来都不是。)你也有被覆盖的风险。

这种"副作用"是无辜的吗

不,很明显。它会与页面上的其他脚本很好地交互吗?不知道。。。这取决于它的用途,以及您希望它与其他类型的脚本相结合。你永远无法制作一个在与其他插件和脚本交互时永远不会失败的"插件",但通过将副作用降至最低,你至少可以尝试将其降至最低。

注意,id不是唯一标识符。尽管在一个特定的时间,文档中应该只有一个具有给定ID的元素,但(a)可以使用相同的ID创建多个元素,并按顺序插入到文档中(也许一个元素用相同的ID替换另一个元素),以及(b)人们仍然使用重复的ID,即使这是错误的。这两种情况都会导致缓存收集旧的、不再使用的元素,并不适当地返回它们。

不幸的是,没有JavaScript函数来获取任意对象的标量/哈希唯一标识符;获得对象身份的唯一方法是CCD_ 13——与其他对象进行比较。

另一种常见的方法是向节点添加一个任意的新属性(IE术语中的"expando"),并带有一个随机的、真正唯一的ID。标准并不能保证expando能够工作,但它从第一天起就在所有浏览器中都能工作,并且很常用。

例如,jQuery就是这样唯一地识别元素的,如果你正在为jQuery编写插件,你可以尝试利用这一点——jQuery.expando保存用于此目的的任意expando属性的名称。。。或者,在文档化的特征集中,data()可以用于将您自己的元数据添加到元素中,包括您自己的另一个唯一ID。

Expandos确实有一些令人不快的副作用,包括意外地将它们作为IE<9(不能区分属性和属性),但如果您无论如何都在使用jQuery,您可能不会有任何损失。

对我的decorator进行优化值得吗?

取决于你期望在一页上有多少。将每个项目与其他项目进行比较是O(n²)运算;如果n较低,则可以忍受(考虑到副作用,可能更可取),但随着n的增长,很快变得无法控制。

相关文章: