2

我在将 javascript 代码模块用于 firefox 插件时遇到了这种奇怪的行为。我不确定这是相互导入的错误还是糟糕的设计。

因此,假设有 3 个模块 a、b 和 c。

一个.js

var EXPORTED_SYMBOLS = ["a"];                                                       
Components.utils.import("resource://mymodule/c.js");                                 
Components.utils.import("resource://mymodule/b.js");                                 

var a = {                                                                           
    init: function() {                                                              
        dump("A init\n");                                                           
        b.init();                                                                   
    }                                                                               
};     

b.js

var EXPORTED_SYMBOLS = ["b"];
Components.utils.import("resource://mymodule/c.js");

var b = {
    init : function() {
        try {
            dump("B init\n");
            dump(c.foo() + "\n");
        } catch (e) {
            dump("Error C init : " + e.message + "\n");
        }
    }
};

c.js

var EXPORTED_SYMBOLS = ["c"];
Components.utils.import("resource://mymodule/b.js");

var c = {
    foo : function() {
        return "C Foo";
    },
};

a.init() 被外部调用。现在使用上面的代码,我从 b 中为 'c' 打了一个未定义的。

A init
B init
Error C init : c is undefined

经过一些故障排除后,我意识到要纠正这个问题,

  • 我可以交换 a.js 中的导入(b 在 c 之前导入)
  • 或者我可以删除相互导入(从 c 中删除 b 的导入)使用其中任何一个,事情都很好。

在我的实际代码中,b 和 c 代表一些与 UI 相关的东西,它们具有相互依赖关系。我可以完全摆脱模块的相互导入,并为其中一个注册回调函数。但我想知道是什么导致了这种行为。据我了解,文档对模块之间的导入没有任何严格的指导方针。我还知道,由于模块缓存,一个模块在多次导入时将被共享。但不知何故无法解释这一点。我在这里做错了什么?

4

1 回答 1

1

我对正在发生的事情有一个理论,尽管我没有尝试在调试器中运行代码以确保:

  • a.js 运行并导入 c.js
  • c.js 运行并导入 b.js(之前c已定义!)
  • b.js 运行并导入 c.js。但是 c.js 并没有再次运行,因为之前已经导入过一次。
  • 由于c在 c.js 范围内仍然未定义(因为c.js还没有继续运行;它仍在等待import第 2 行的调用返回),c = undefined因此被注入到 b.js 范围内。
  • b.js 完成执行。
  • c.js 完成执行。
  • a.js 完成执行。

所以 b.js 永远不会收到有效的绑定c,并b.init()在尝试访问时抛出异常c.foo

如果这个理论是正确的,我认为你可以通过将 b.js 和 c.js 中的导入调用移动到这些文件的底部来修复错误。

于 2014-02-12T01:35:49.983 回答