能否在不转译的情况下从ECMAScript5脚本调用ECMAScript6脚本?
嘿,这个问题问得特别实在——毕竟没人想平白多一道转译工序对吧?我来给你梳理几个不用转译就能让ES5系统调用ES6模块的通用方案,分场景来看:
前端浏览器场景:利用原生模块支持
现在绝大多数现代浏览器都原生支持ES6模块了,你只需要简单配置就能打通ES5和ES6模块:
- 引入ES6模块时,给
<script>标签加上type="module"属性:<script type="module" src="./your-es6-module.js"></script> - 要是你的ES5代码是传统的全局脚本(不带
type="module"),直接访问模块导出的内容会有作用域问题。这时候有两个办法:- 在ES6模块里把需要暴露的内容挂载到全局对象(比如
window)上:
这样ES5代码里就能直接调用// your-es6-module.js export function foo() { console.log('Hello from ES6 module'); } window.foo = foo; // 挂载到全局foo()了。 - 用动态
import()函数在ES5代码里异步加载模块:
注意动态// ES5代码 import('./your-es6-module.js').then(module => { module.foo(); // 调用模块导出的方法 });import是异步的,要处理好异步逻辑哦。
- 在ES6模块里把需要暴露的内容挂载到全局对象(比如
Node.js环境:配置模块类型兼容
从Node.js 12开始就原生支持ES6模块了,只需做一点配置:
- 方法一:把你的ES6模块文件后缀改成
.mjs,Node.js会自动识别为ES6模块;ES5的CommonJS文件保持.js后缀,用require加载即可。 - 方法二:在项目根目录的
package.json里添加"type": "module"字段,这样所有.js文件都会被当作ES6模块处理。如果有个别ES5的CommonJS文件,可以把后缀改成.cjs。 - ES5的CommonJS代码想要加载ES6模块,可以用动态
import():// ES5的CommonJS文件 async function loadES6Module() { const es6Module = await import('./your-es6-module.js'); es6Module.foo(); } loadES6Module();
兼容旧环境:用第三方模块加载器
如果你的系统必须跑在不支持ES6模块的旧环境(比如老版本浏览器或Node.js),又不想转译,试试用SystemJS这类模块加载器:
- 先在页面里引入SystemJS脚本
- 然后在ES5代码里用SystemJS加载ES6模块:
SystemJS会在运行时解析ES6模块语法,帮你处理模块依赖和加载,不用提前转译。// ES5代码 System.import('./your-es6-module.js').then(module => { module.foo(); });
几个关键提醒
- 模块作用域是核心差异:ES6模块有独立作用域,不像ES5脚本默认在全局作用域,所以直接在ES5代码里引用模块变量会找不到,必须通过上面的方式获取。
- 语法特性和模块系统要区分开:如果你的ES6模块里用了箭头函数、解构赋值这类ES6+语法,而运行环境不支持这些语法,就算能加载模块还是会报错。这种情况你可能只需要转译语法特性,不用转译模块系统,工作量会小很多。
内容的提问来源于stack exchange,提问作者chris
相关产品推荐
相关产品推荐

