【问题标题】:Why Doesn't JQuery Expose its UUID Functionality?为什么 JQuery 不公开其 UUID 功能?
【发布时间】:2011-10-25 09:34:18
【问题描述】:

在底层,JQuery 使用“UUID”映射(只是它维护为 jQuery.uuid 的计数器)来解决众所周知的内存泄漏问题,当您从 Javascript 将属性附加到 DOM 中的标签时.代替这样做,JQuery 使用$.data(tag, name, value) 将数据存储在与 uuid 键控的映射中(可以通过检查 tag[jQuery.expando] 来确定键)。

虽然$.data() 非常有用,但有时您希望将数据映射到标签而不将该数据转储到一个全局存储桶中 - 您需要自己的较小数据存储桶,例如,检查长度或循环。

作为一个人为的示例,假设您的图标在单击时会在 4 种状态之一中旋转。当一个处于状态 2 时,您希望将其添加到状态 2 的图标数组中。最明显的方法是将标签添加到数组中;但是这样做会造成内存泄漏。您可以在复选框上调用 $.data(),但这并不能完全完成您想要做的事情 - 您必须遍历所有复选框,检查 $.data() 以找出哪些是和不是在列表中。

您需要将一些抽象的标签存储在一个数组中,这就是 jQuery 的 UUID。您可以编写自己的 UUID 功能,但理想情况下,出于代码大小和质量原因,您只需利用 JQuery 已经内置的 UUID 功能。您可以通过调用$.data(tag, 'irrelevant', 1) 让JQuery 将UUID 隐式附加到标签,然后检查tag[jQuery.expando] 以获取其UUID,最后在列表中使用它......但这有点小技巧。真正理想的是在公共 API 中公开以下内容:

$.getUuid(tag):如果不存在 UUID,则检查并创建 UUID - 理想情况下,该方法从 $.data() 中分解出来,并为传入的标签创建或获取 uuid。

那么,这是否有原因在 jQuery 中没有被考虑到它自己的方法中?这在某种程度上有害吗?它只是从来没有看起来有用的东西吗?

我应该注意,我实际上已经在我们使用的 jQuery 版本中考虑了它,它非常有帮助。但也许我在使用中没有遇到潜在的风险。我也知道有一个插件可以实现这一点,但它有点损坏 - 并且有 2 个代码路径来执行相同的 UUID 功能既有点浪费又有点脆弱。

【问题讨论】:

  • 我认为这是一个很好的问题,但将其通过电子邮件发送给 jQuery 维护人员可能更有效 :-) 或者,记录一个错误 - 他们确实非常重视错误列表。跨度>
  • 我认为他们必须先重命名该功能,然后才能将其暴露给外界:顺序整数除了通用唯一标识符之外的一切。
  • @Pointy 好的,我会这样做 - 我真的很感谢更广泛的 Stack Overflow 社区和针对此类问题的评论排名系统。
  • 请注意,这是向 JQuery 团队提出的,但(非常粗鲁地)拒绝了,基本上是说,我们收到了很多请求,你自己写吧。

标签: jquery uuid expando


【解决方案1】:

这个被提交给 jQuery 团队并被拒绝。

但是,您可以像这样维护一个将垃圾收集委托给 jQuery 的标签列表:

http://jsfiddle.net/b9chris/Un2mH/

基本代码是:

sets[oldIndex] = sets[oldIndex].not(this);
sets[index] = sets[index].add(this);

虽然这会产生单独的内存负担 - 这些方法不仅仅是向数组添加标签,它们还维护此集合的先前状态的堆栈(.pushStack() 在内部调用)。如果页面长期存在大量用户操作,则集合将无限增长。为了防止这种情况,您可以破解对象以删除堆栈:

sets[oldIndex] = sets[oldIndex].not(this);
sets[oldIndex].prevObject = null;
sets[index] = sets[index].add(this);
sets[index].prevObject = null;

浪费了一些 CPU 周期,但足够干净。

【讨论】:

    【解决方案2】:

    我认为这里显而易见的答案是 jQuery 构建了他们的 uuid 供内部使用,并且没有看到一个很好的理由或很大的需求来打扰它公开消费。这并不意味着原因不存在,只是它们似乎还不够重要,无法将其排在要处理的事情列表的首位。

    用作唯一 ID 的单调递增计数器实现起来非常简单,我已经多次使用过。我觉得这样做不需要类库支持。

    我认为您因为保留对象引用而担心内存泄漏有点夸大其词。首先,如果您摆脱对象并忘记摆脱对它的某些引用,这只是内存泄漏。这只是垃圾收集语言中的一般规则,您必须“知道”在哪里保存对可能会删除的对象的引用,并在打算释放对象时清理这些引用。

    其次,如果您在每页中多次执行相同的操作,或者对象非常非常大,这只是有意义的内存泄漏。当你进入下一页时,它们都会被清理掉,所以它不像是永远积累的东西,除非你从不离开那个浏览器页面并且一遍又一遍地做同样的事情,这涉及到删除的对象,但没有删除的引用。

    第三,jQuery 的 .data() 机制尝试在使用 DOM 对象时为您解决很多问题。

    第四,在您设计的示例中,这不会造成内存泄漏,除非您在状态 2 不再有效或不再使用时不清理您的图标数组。如果您清理它,那么在该数组中存储直接 DOM 引用就没有问题。如果你不清理数组,那么即使数组本身也是内存泄漏,即使它里面有抽象的 uuid 而不是 DOM 引用。大多数时候,使用抽象引用只是比需要做的工作多得多。

    同样,即使你让它泄漏,只有当页面的生命周期很长并且你反复创建和释放对象但没有以引用随时间累积的方式清除对它们的所有引用时,泄漏才重要并且这样做足以使它们引起的内存泄漏是有意义的。我一直在 JS 变量中保留对 DOM 对象的引用。我只是小心地确保在不再需要它们时将它们清空,这样我知道 DOM 对象可以在以后的某个时候被释放。

    【讨论】:

    • 我不确定您是否了解导致浏览器内存泄漏的原因。例如,一个 uuid 数组只是一个数字数组。这: var 数组 = [1,2,3,4];不会在 Javascript 中泄漏 - 就浏览器而言,uuid 数组是相同的。现在添加到标签中的 uuid 如果不清理它确实会泄漏,但这是利用现有 jQuery 代码的好处——你重用所有经过充分测试的代码来处理添加、跟踪和清理,而不是拼凑你的一起拥有。所以,我意识到我可以自己写——这不是一个好主意。
    • 我绝对理解导致浏览器内存泄漏的原因。我以前用真实的代码追踪过它们。我不明白的是你认为你需要使用 uuids 来防止 jQuery 尚未提供功能的泄漏。如果我理解你的例子,它不会泄漏。将 DOM 对象引用存储在数组中本身不会导致泄漏,而不是存储 uuid。这将需要其他情况,例如从 DOM 中删除 DOM 对象并释放所有其他引用以将其转变为泄漏,然后执行足够多的时间以保持相关性。
    • 正确 - 它基本上造成了可能发生泄漏的情况(只需要删除 DOM),我不想编写脆弱的代码。
    • 另外,可能需要移除一个 DOM 才能造成泄漏。但是可能需要数千次 DOM 删除(没有相应的 JS 引用清理)才能造成严重的泄漏。在某些情况下可能会发生这种情况,但不是通常的网页。
    猜你喜欢
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 2018-12-10
    • 2011-01-04
    • 1970-01-01
    • 2015-09-20
    • 2020-05-09
    • 2010-11-18
    相关资源
    最近更新 更多