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

JavaScript中同时定义和未定义的对象(在FireFox扩展中),javascript,firefox-addon,Javascript,Firefox Addon,我正在FireFox扩展中查找一个。我终于自己看到了(我以前只收到过报告),但我不明白我所看到的是怎么可能的 错误控制台中来自my extension的一条错误消息是“gBrowser未定义”。这本身就足够令人惊讶了,因为覆盖层位于browser.xul和navigator.xul之上,我希望gBrowser可以从这两个站点获得。更糟糕的是实际发生的地方:第101行。也就是说,在函数isTopLevelDocument中,该函数仅从onContentLoaded调用,此处仅从onloaded调用

我正在FireFox扩展中查找一个。我终于自己看到了(我以前只收到过报告),但我不明白我所看到的是怎么可能的

错误控制台中来自my extension的一条错误消息是“gBrowser未定义”。这本身就足够令人惊讶了,因为覆盖层位于browser.xul和navigator.xul之上,我希望
gBrowser
可以从这两个站点获得。更糟糕的是实际发生的地方:第101行。也就是说,在函数
isTopLevelDocument
中,该函数仅从
onContentLoaded
调用,此处仅从
onloaded
调用:

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
以某种方式被定义为足以调用这些函数,但没有在它们内部定义

最后,在executejs中执行
typeof(nextplease)
将返回“object”。同样适用于
gBrowser

这怎么会发生?有什么想法吗?

对于第二种情况:

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);
}

我不确定发生了什么(代码在哪个上下文中运行,因此为什么没有看到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( ... )

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

那么,代码最初运行的上下文不一定与各种定义函数运行的上下文相同。(我不是XUL开发人员,所以我只是从第一原理开始工作。)如果将“gBrowser”和“nextplease”隐藏到“nextplease”对象本身,会发生什么?还是在定义的结尾?@Pointy:说得很好。这可能是全局变量不好的一个很好的例子。闭包可能是一种方式……您的代码是否可能意外地在文档或内容中运行,而不是在chrome中运行?这可能会导致gBrowser突然变得未定义,因为它不暴露于内容。这似乎是目前为止唯一合理的想法。有没有一种简单(或不是那么简单)的方法来测试函数是否在chrome中运行?