【问题标题】:Javascript - Remove references to my object from external arraysJavascript - 从外部数组中删除对我的对象的引用
【发布时间】:2010-12-18 13:03:13
【问题描述】:

我在取消引用 Javascript 对象并将其设置为 NULL 时遇到问题。

在这里,我有一个支持递归子目录删除的文件夹实现。请查看我的 cmets 以了解我的困境。

function Folder(name, DOM_rows) {
    this.name = name;
    this.files = [].concat(DOM_rows);
    this.subdirs = [];
}

Folder.prototype.AddDir(name, DOM_rows) {
   this.subdirs.push(new Folder(name, DOM_rows));
}

Folder.prototype.RemoveDir(folder) {
   var stack = [folder];
   while(stack.length > 0) {
      var cur = stack.pop();
      // do a post-order depth-first traversal, so dig to the deepest subdir:
      if(cur.subdirs.length > 0) {
          while(cur.subdirs.length > 0) { stack.push(cur.subdirs.pop()); }
      } else {
          // arrived at a leaf-level:
          cur.files = null;
          // now how do I delete cur from it's parent's subdirs array?
          // the only way I know how is to keep a "cur.parentDir" reference,
          // then find parent.subdirs[ index of cur ] and slice it out.
          // How can I do the JS-equivalent of *cur = NULL?
      }
   }
}

【问题讨论】:

  • 有什么原因你没有对RemoveDir 使用递归?是否有任何示例中未显示的附加处理需要在文件或文件夹被删除时执行?
  • @outis:我只是更喜欢迭代而不是递归。在某些情况下,递归执行它可能更节省空间,但我知道宽度(每个级别的子目录数量)相对于深度会很小。实际上,我的应用程序与文件夹和文件无关,但它具有相同的结构。我的“文件夹”对象还有更多属性需要处理和删除。

标签: javascript null dereference


【解决方案1】:

请注意,您并没有想象中那么大的问题,因为除了 RemoveDir 中的 folder 之外的所有子目录都将通过 stack.push(cur.subdirs.pop()); 行从其父目录的 subdir 中删除

要在父目录中查找子目录,您可以使用对象作为字典而不是 subdirs 的数组:

function Folder(name, DOM_rows, parent) {
    this.name = name;
    this.parent = parent;
    this.files = [].concat(DOM_rows);
    this.subdirs = {};
    this.subdirCount = 0;
}

Folder.prototype.AddDir = function (name, DOM_rows) {
    if (this.subdirs[name]) {
        return null;
    }
    ++this.subdirCount;
    return this.subdirs[name] = new Folder(name, DOM_rows, this);
}

给定一个文件夹,您可以使用以下命令从父文件夹中删除该文件夹:

delete folder.parent.subdirs[folder.name];

这是预购版本:

Folder.prototype.RemoveDir = function (folder) {
  if (this.subdirs[folder.name] === folder) {
      var stack = [folder];
      while(stack.length > 0) {
          var cur = stack.pop();
          // pre-order
          delete cur.files;
          // if there's other processing to be done, now's the time to do it
          for (subdir in cur.subdirs) {
              stack.push(cur.subdirs[subdir]);
              delete cur.subdirs[subdir];
          }
          // it's unnecessary to set subdir count, since 'cur' has been deleted
          //cur.subdirCount = 0;
      }
      delete this.subdirs[folder.name];
      --this.subdirCount;
  }
}

还有递归后序版本:

Folder.prototype.RemoveChildren = function () {
    for (subdir in this.subdirs) {
        this.RemoveDir(this.subdirs[subdir]);
    }
}

Folder.prototype.RemoveDir = function (folder) {
    if (this.subdirs[folder.name] === folder) {
        folder.RemoveChildren();
        folder.files = [];
        delete this.subdirs[folder.name];
        --this.subdirCount;
    }
}

还有迭代后序版:

Array.prototype.top = function () { return this[this.length-1]; }

Folder.prototype.RemoveDir = function (folder) {
  if (this.subdirs[folder.name] === folder) {
      var stack = [folder];
      while(stack.length > 0) {
          var cur = stack.top();
          if (cur.subdirCount > 0) {
              for (subdir in cur.subdirs) {
                  stack.push(cur.subdirs[subdir]);
                  delete cur.subdirs[subdir];
              }
              cur.subdirCount = 0;
          } else {
              stack.pop();
              delete cur.files;
              // other post-order processing
          }
      }
      delete this.subdirs[folder.name];
  }
}

不过,除非您在处理已删除的文件和文件夹时需要采取额外的步骤,否则很简单:

Folder.prototype.RemoveDir = function (folder) {
  if (this.subdirs[folder.name] === folder) {
    delete this.subdirs[folder.name];
  }
}

应该够了。

【讨论】:

  • 谢谢 outis - 你为此去了城里 - 为 .top() 原型 +1。我需要释放对 DOM 元素的引用,所以不能只删除对文件夹的引用,以免在 IE 中出现内存泄漏的风险。
【解决方案2】:

一切都是 javascript 是按值传递的,所以 "*cur=NULL" 是不可能的。你这里基本上有以下选择

  • 按照您的建议使用 parentID
  • 如果您的文件夹层次结构有一个众所周知的根,请从该根浏览以查找父对象
  • 使用类似 DOM removeChild(在父节点上调用),而不是 removeNode(在节点本身上调用)。

【讨论】:

  • 你的意思是通过引用传递吗?
  • 展开:Javascript 是按值传递的,但对象是通过引用存储的。它有时被称为“按参考值传递”。这就是为什么 function foo(obj) {obj.qux = 1;} 的影响在对 foo 的调用之外可见,但在 function bar(obj) {obj = {qux: 1};} 之外不可见。
  • @outis:同意,只有原始参数(stringnumberbooleannullnullundefined)“按值”传递,对象“按引用”传递"(或者如你所说,引用作为值传递:)。
  • 我真的很希望我们通过参考参考。 :)
【解决方案3】:

我今天也想做同样的事情。 我通过将对象的索引存储为对象本身的属性来解决它。

当你添加它时:

myObj.ID = myArr.push(myObj);

所以删除它你

myArr[myObj.ID] = null;

我猜你现在已经解决了,但你几乎可以做同样的事情;而且比使用对象更简单。

【讨论】:

    猜你喜欢
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-19
    • 1970-01-01
    • 2016-11-08
    • 2020-12-07
    相关资源
    最近更新 更多