代码之家  ›  专栏  ›  技术社区  ›  Neutrino

为什么在模块中为窗口分配函数不起作用?

  •  0
  • Neutrino  · 技术社区  · 4 月前

    module.mjs

    console.log('module1 loaded');
    
    window.module1_function = () => {
       console.log('module1_function executed');
       return 42;
    }
    

    index.html

    <script defer type="module" src="./js/module1.mjs"></script>
    
    <script defer>
       module1_function();
    </script>
    

    输出

    Uncaught ReferenceError: module1_function is not defined
    
    module1 loaded
    

    正如你所看到的,它失败了。调用时,函数未定义。在函数被调用之前,模块不会被加载。正在执行 module1_function() 在控制台中,函数成功运行。

    为什么?

    defer 应导致内联脚本在之后才被处理 module.mjs 已执行,此时应分配函数并使其可用。

    如何使此模块中的函数在脚本中可用?我不想将脚本转换为模块并导入函数。

    1 回复  |  直到 4 月前
        1
  •  2
  •   Davi    4 月前

    访问 module1_function window 在非模块脚本中的对象,对我来说最简单的解决方案似乎是添加一个 load 将事件监听器插入到非模块脚本中:

    <script>
    window.addEventListener('load', () => {
      console.log(typeof window.module1_function); // should log 'function' 
    });
    </script>
    

    这应该等待 任何东西 要加载(即使是带有 async 属性),然后执行回调。

    供参考 MDN 关于模块和 defer 属性(第3点):

    加载模块脚本时不需要使用defer属性[…];模块会自动延期。

    OTOH你的另一个选择是 dynamic imports -额外的好处是,您根本不需要将函数附加到全局范围(至少您不应该这样做 不得不 做吧)。但是,您显示的模块代码没有 出口 所以你也必须改变这一点:

    在module1.mjs中:

    export const module1_function = () => {
      console.log('module1_function executed');
      return 42;
    };
    

    在HTML内部:

    <script>
    import('./js/module1.mjs').then((module) => {
      module.module1_function();
    });
    </script>