JavaScript类和jQuery对象之间的循环依赖

Ian*_*ark 6 javascript oop jquery circular-dependency

我正在尝试使用现有的工作代码库并使用JavaScript使其面向对象.我的系统采用JSON包含一对多关系中的,并在页面上显示这一点.这些项目可以移动到不同的组中,并且还需要计算它们在这些组中的位置.因此,需要建立能够了解其周围的群组和门票的事件.

我正在使用John Resig的简单JavaScript继承设置来建立两个类,Item并且Group.当每个Item实例化时,它会引用它的父级Group.当我想要建立我的事件时,我的问题出现了,并且最容易用以下函数解释:

var Group = Class.extend({
  ...
  // Calculate where to place the new item within the group
  calculate_new_position: function(item) {
    var pos = -1;
    // Loop through all DOM items in groups body
    $(".item", this.elBody).each(function(i) {

      // Retrieve it's class object
      var next = $(this).data("_obj");

      // Calculating things using the class reference
      var lowerPrio = item.tData.priority < next.tData.priority,
          lowerId =  item.id < next.id;

      if(lowerPrio || lowerId) {
        pos = i;
        return false;
      }
    });
    return pos;
  },
  ...
)};
Run Code Online (Sandbox Code Playgroud)

注意使用.data("_obj")上面的代码片段.基本上,当我需要对项目进行排序时,我需要知道对应于组中每个项目的DOM(视图/控制器)的对象(模型).现在,我可以建立我的Group类,这样当我创建每个类时,我会在我的内部Item添加对它的引用Group(例如so Group.items = [i1, i2...]),然后我可以迭代Item实例,而不是迭代DOM元素.但是我想我会遇到类似的问题,例如当我想要Item进入一个不同的时候Group(就像Group不知道的那样Item).

长话短说:有一个类在实例化时创建一个DOM元素然后反过来指向类,这本质上是危险/天真/没有意义吗?这感觉就像循环依赖,以及一些递归的噩梦,但也许对一个对象的引用并不是一件可怕的事情.如果我正在做其他任何真正愚蠢的事情,并且有一个更简单的方法,那么请指出它.

Hof*_*ann 2

任何现代浏览器垃圾收集器都可以处理循环引用。如果您丢失了对该对象的所有引用并从 DOM 中删除了所有 HTML 节点(当它在 DOM 中时,浏览器将看到对您的对象的引用并阻止它被垃圾收集),您的对象将被垃圾收集。但要小心事件处理程序,如果您不删除它们,它们可以保留引用。

我听说一些旧版本的 IE 确实存在循环引用问题。有关更深入的解释: Precise opportunity of JavaScript <-> DOMcircular Reference issues

从这个答案来看:jQuery 的 .data() 使事情变得更加可靠,因为旧版本的 IE 对于添加到 DOM 元素的属性有一个特殊的问题,并且没有正确处理涉及这些属性中的数据的循环引用,因此不会释放应该发生的事情(泄漏)。.data() 通过仅使用 DOM 元素上的一个附加属性来解决这个问题,该属性是一个安全的、非泄漏的字符串。该字符串是 javascript 对象的键,该对象可以包含您想要与 DOM 元素关联的所有属性。因为这些属性都存储在纯 JavaScript 中,浏览器没有循环引用错误,所以这样做不会导致泄漏。

您可能想研究一下 D3.js,它的功能与您想要的类似。它将数据绑定到 DOM 元素并提供生成可视化的简单方法: http://d3js.org/

使用 D3,您可以将数字数组绑定到圆形 SVG 标签数组,并使每个圆形具有基于与其关联的数组的编号的半径。

编辑:我忘了提及,如果您使用 $.remove() ,事件处理程序也会被删除。但是,如果您有一个位于闭包内的事件处理程序,并且该闭包还引用了您的(已删除的)HTML 节点,则它不会被垃圾收集。这通常不是一个大问题,因为一旦它在 DOM 之外,它就不会消耗太多资源,而且据我所知,不可能递归地堆叠这些闭包引用。