0

考虑以下工作正常的(简化)示例:

var tabs = window.gBrowser.tabs;
for (var i = 2, len = tabs.length; i < len; i++) {
  var uri = window.gBrowser.getBrowserAtIndex(i).currentURI.spec;
}

以下有时会在最后一个选项卡上失败并显示消息window.gBrowser.getBrowserAtIndex(...) 未定义

var tabs = window.gBrowser.tabs;
for (var i = 2, len = tabs.length; i < len; i++) {
  var uri = window.gBrowser.getBrowserAtIndex(i).currentURI.spec;
  window.gBrowser.removeTab(window.gBrowser.tabContainer.childNodes[i]);
}

我不明白为什么它会失败,为什么它只是有时而不是一直失败。

有没有其他方法可以用来代替gBrowser.getBrowserAtIndex(i)获取标签的 URL?

4

2 回答 2

2

根本问题是它tabs不是一个数组而是一个 NodeList,它是一个实时集合。当您调用时removeTab(),更改会反映在 NodeList(长度、索引)中。

为了避免这些副作用,将其转换为真正的数组

var tabsArr = [].slice.call(gBrowser.tabs);
于 2014-10-06T11:35:30.147 回答
1

您似乎正在关闭一个循环内的选项卡,您在该循环中存储了初始选项卡数量len = tabs.length,然后当现有选项卡的数量可能由于您的操作而发生变化时,与原始选项卡数量进行比较。

构造:在长度不变
for (let i = 2, len = tabs.length; i < len; i++) {...}
的情况下更有效。tabs但是,在这种情况下,您正在更改选项卡的数量,并且需要在tabs.length每次检查此循环的终止条件时进行比较。所以:
for (let i = 2, len = tabs.length; i < len; i++) {...}
事实上,您当前循环并不总是失败的唯一原因window.gBrowser.removeTab()是在标签实际被删除之前返回。您正在竞相查看是否在实际删除任何选项卡之前完成了循环。

然而,这不是唯一的问题。您正在删除当前索引的选项卡。在大多数情况下,如果选项卡被删除,就像大多数数组一样,剩余的较高索引选项卡会向下移动到您已经在操作的索引处。当前循环不会常规跳过所有其他选项卡的唯一原因是window.gBrowser.removeTab()在实际删除您当前索引的选项卡之前返回。您实际上只是在看到undefined错误的情况下跳过一个选项卡。

你的循环真的应该是这样的:
for (let i = tabs.length - 1; i >=2; i--) {...}
这样你从列表的末尾开始并从那里删除。undefined这通过消除需要在实际删除任何选项卡之前完成整个过程的竞争条件来防止问题和跳过选项卡的可能性。

于 2014-10-06T08:55:57.257 回答