JavaScript中的对象同时定义和未定义(在FireFox扩展中)

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (19)

我正在追踪FireFox扩展中的一个错误。我终于成功地亲眼看到了它(我以前只有过报道),我无法理解我所看到的是如何可能的。

在错误控制台中,来自我的扩展程序的一条错误消息是“gBrowser未定义”。这本身就足够让人惊讶,因为overlay覆盖了browser.xul和navigator.xul,我希望gBrowser它们都可以使用。更糟的是它发生的实际位置:nextplease.js的第101 。也就是说,在函数内部,只能从这里isTopLevelDocument调用onContentLoaded,这个函数只能从onLoad这里调用:

gBrowser.addEventListener(this.loadType, function (event) {
    nextplease.loadListener.onContentLoaded(event);
},
true);

所以gBrowser被定义onLoad,但在某种程度上未定义isTopLevelDocument

当我试图实际使用扩展名时,出现另一个错误:“nextplease未定义”。有趣的是,它发生在853和857行。也就是在函数内部

nextplease.getNextLink = function () {
    nextplease.getLink(window.content, nextplease.NextPhrasesMap, nextplease.NextImagesMap, nextplease.isNextRegExp, nextplease.NEXT_SEARCH_TYPE);
}

nextplease.getPrevLink = function () {
    nextplease.getLink(window.content, nextplease.PrevPhrasesMap, nextplease.PrevImagesMap, nextplease.isPrevRegExp, nextplease.PREV_SEARCH_TYPE);
}

所以nextplease不知怎么定义足以调用这些函数,但没有在它们内部定义。

最后,typeof(nextplease)在Execute JS中执行返回“object”。同样的gBrowser

这怎么会发生?有任何想法吗?

提问于
用户回答回答于

我不确定发生了什么(代码在哪个上下文中运行,以及为什么它没有看到gbrowser和其他全局变量),但是对于未定义gbrowser的简单解决方法是获取对主窗口的引用并从中访问它那里:

var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                     .getInterface(Components.interfaces.nsIWebNavigation)
                     .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
                     .rootTreeItem
                     .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                     .getInterface(Components.interfaces.nsIDOMWindow);

mainWindow.gbrowser.addEventListener( ... )

这应该独立于代码运行的上下文,因为你不会依赖全局变量。

用户回答回答于

对于第二种情况:

nextplease.getNextLink = function () {
    nextplease.getLink(window.content, nextplease.NextPhrasesMap, nextplease.NextImagesMap, nextplease.isNextRegExp, nextplease.NEXT_SEARCH_TYPE);
}

nextplease.getPrevLink = function () {
    nextplease.getLink(window.content, nextplease.PrevPhrasesMap, nextplease.PrevImagesMap, nextplease.isPrevRegExp, nextplease.PREV_SEARCH_TYPE);
}

我会试试这个:

nextplease.getNextLink = function () {
    this.getLink(window.content, this.NextPhrasesMap, this.NextImagesMap, this.isNextRegExp, this.NEXT_SEARCH_TYPE);
}

nextplease.getPrevLink = function () {
    this.getLink(window.content, this.PrevPhrasesMap, this.PrevImagesMap, this.isPrevRegExp, this.PREV_SEARCH_TYPE);
}

扫码关注云+社区