繁体   English   中英

如何在 Javascript 中检查脚本是否作为 ES6 模块运行(以便它可以“导出”)?

[英]How do I check if a script is running as a ES6 module (so that it can `export`), in Javascript?

我想制作一个 Javascript 文件

  • export s 它的内容(例如一个类),如果它可以export (例如它已经加载了<script type="module">
  • 否则,将其内容分配给全局变量,例如windowglobal

例如,让我们假设这样一个文件print.js

案例A

可以像这样使用它:

<script type="module">
    import print_things from "./print.js";
    print_things("Javascript innovation");
</script>

案例B

或者,

<script src="./print.js"></script>
<script>
    print_things("Hmmmmmmm.");
</script>

目前,使用export会使脚本在案例 B中抛出错误: Uncaught SyntaxError: Unexpected token export 因此,它必须知道export在其运行的环境中是否可用,以支持这两种用例。 我该怎么做呢?

查看UMD (通用模块定义)。 这个例子

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['exports', 'b'], function (exports, b) {
            factory((root.commonJsStrictGlobal = exports), b);
        });
    } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
        // CommonJS
        factory(exports, require('b'));
    } else {
        // Browser globals
        factory((root.commonJsStrictGlobal = {}), root.b);
    }
}(typeof self !== 'undefined' ? self : this, function (exports, b) {
    // Use b in some fashion.

    // attach properties to the exports object to define
    // the exported module properties.
    exports.action = function () {};
}));

理解type=module的浏览器应该忽略带有nomodule属性的脚本。 这意味着您可以为支持模块的浏览器提供模块树,同时为其他浏览器提供回退。

<script type="module" src="module.js"></script>
<script nomodule src="fallback.js"></script>

注意:你可能不应该在现实世界中使用它,但它完全有效的,并且完全符合你的要求。)
这是您的print.js的实现:

function print_things(msg) {
   console.log(msg)
}
if(0)typeof await/2//2; export default print_things

 <script type=module> // (renamed to avoid name collision) import print_things2 from "https://12Me21.github.io/external/print.js" print_things2("Javascript innovation") </script> <script src="https://12Me21.github.io/external/print.js"></script> <script> print_things("Hmmmmmmm.") </script>
此语法将从非模块脚本中“隐藏”导出语句,因为await/2//2; ... await/2//2; ...根据上下文进行不同的解析:

  • 模块异步函数中:
    await (运算符) /2/ (正则表达式) / (除) 2 (数字)
  • 在普通脚本中:
    await (variable) / (divide) 2 (number) //2 ... ( comment )

当它被解析为注释时,该行的其余部分将被忽略。 因此, export语句仅对模块脚本可见。

这是规范的相关部分: 15.8 Async Function Definitions > Syntax > AwaitExpression > Note 1

兼容性

作为一个非模块脚本,它应该可以在任何浏览器中运行(甚至是 Internet Explorer 的旧版本等),并且在启用"use strict"的情况下仍然有效

但是,将其作为模块加载需要支持“顶级等待”,这是在模块本身之后几年添加的(~2021 vs~2018),所以请记住这一点。
(它也适用于 nodejs,在任何一种模式下)

我在自己编写的库中使用了这个技巧,几个月来它在多个环境中都运行良好。 但是,它导致了一些外部工具(框架、编译器、压缩器等)的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM