32

ES Modules 和 ES5 Script 之间相互引用

 6 years ago
source link: https://harttle.land/2019/03/21/esmodule-interop.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

ES5 没有定义文件之间引用方式,在浏览器中文件之间引用需要通过类似 define , require , __webpack_require__ 这样的全局变量,它们由不同的模块化框架定义。 ES Modules 从标准上定义了 JS 文件间的引用方式,而且现在主流浏览器和 Node.js 都已经有了实现。 本文介绍 Node.js 中新写的 ES Modules 怎么和旧的 CommonJS 模块相互引用, 以及如何引用 npm 上成千上万的 CommonJS 模块。即 ES Modules 和 ES5 Script 间的互操作问题 。 ES5 Script 有多种模块化实现,本文集中讨论 Node.js 中的 CommonJS。

ES Modules 和 ES5 Script 的区别

  • CommonJS 中 module.exports 会被拷贝一份,这意味着 export 的值在变更后引用处还是旧的。ES Modules export 的值会被关联到引用方(通过 ImportEntry/ExportEntry Record 实现);但
  • ES Modules 采用 “strict” 模式解析,就像头部写了 “use strict” 一样。
  • ES5 Script 不允许使用 import from 语句。
  • 浏览器使用 CORS 模式来获取 ES Modules,因此如果模块脚本跨域需要设置CORS HTTP 头,比如 Access-Control-Allow-Origin: * ,也就不允许 file:// 协议因为它的 origin 是 null。ES5 Script 默认情况下没有跨域限制。
  • ES5 Script 中 this 指向全局作用于即 window 或 global,ES Modules 中的 this 是 undefined。

因为解析方式有区别,所以解释执行之前需要知道它是 ES Module 还是 Script。 这就是为什么 Node.js 下 ES Modules 要使用新的后缀 .mjs ,浏览器中要设置 script 标签的 type="module"

CommonJS 引用 ES Modules

目前一般 ES Modules 都会编译成 CommonJS,因此 CommonJS 直接引用 ES Modules 的情况比较少。 如果要用,需要使用动态 import

const foo = await import('./foo.mjs')

ES Modules 引用 CommonJS

ES Modules 还没有在 Node.js 10 落地,目前需要通过 --experimental-modules 开关来启用。 在 ESM 中可以直接使用 import 语句来引入 CommonJS 模块( module.exports 会被作为 default export):

// a.js in CommonJS
exports.foo = 'foo'

// b.mjs in ES Modules
import a from './a.js'
console.log(a)      // prints {foo: "foo"}

// c.mjs in ES Modules
import * as a from './a.js'
console.log(a)      // prints {default: {foo: "foo"}}

由于 Node 还未支持 ES Modules,目前通常会使用 Babel 或 TypeScript 来编译到 CommonJS。 这些编译工具提供了很多编译选项,可以比 ES Modules 标准做更多地事情。 但有些选项是违反标准的,因此要慎用这些选项

例如,目前 TypeScript 中 import * as a from './a.js' 会返回 a.js 的 default export, 即 {foo: "foo"} 而非 namespace object {default: {foo: "foo"}} 。 开启 allowSyntheticDefaultImports 选项并使用 import a from './a.js' 反而会更符合 ES6 标准。

例如,Babel 和 TypeScript 中都支持 import + require 语法来引入 CommonJS 模块, 这一语法非常方便与 ES5 的 const a = require('./a.js') 来回切换,但这个语法没有定义在 ES6 标准中:

import a = require('./a.js')
console.log(a)  // prints {foo: "foo"}

Recommend

  • 66
    • 掘金 juejin.im 7 years ago
    • Cache

    JavaScript 中的继承:ES3、ES5 和 ES6

    选择一种继承方式 JavaScript 是一门动态语言,动态意味着高灵活性,而这尤其可以体现在继承上面。JavaScript 中的继承有很多种实现方式,可以分成下面四类: Mixin 模式,即属性混入,从一个或多个对象中复制属性到新的对象中 方法借用模式,即

  • 135

    C和Lua之间的相互调用 第一次接触Lua是因为Unity游戏...

  • 70

  • 14
    • blog.csdn.net 4 years ago
    • Cache

    ES5 与 ES6 中类的区别

    ES5 与 ES6 中类的区别 类定义与调用的区别 在 ES5 中主要是通过构造函数方式和原型方式来定义一个类,但是在 ES6 新引入了 class 关键字,使之具有了正式类的能力,类(class)是ECMAScript 中新的基础性语法糖结构。虽然 ES6 类表面上看...

  • 8
    • www.zhangxinxu.top 4 years ago
    • Cache

    ES5中新增的Array方法详细说明

    by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=3220

  • 4

    如果以前问我ES5的继承和ES6的继承有什么区别,我一定会自信的说没有区别,不过是语法糖而已,充其量也就是写法有区别,但是现在我会假装思考一下,然后说虽然只是语法糖,但也是有点小区别的,那么具体有什么区别呢,不要走开,下文...

  • 2

  • 8

    CXX库提供Rust和C+ 之间的安全相互调用 CXX库提供了一种安全的机制,用于从 Rust 调用 C++ 代码和从 C++ 调用 Rust 代码。它开辟了一个共性机制,其中 Rust 和 C++ 在语义上非常相似,并指导程序员在这个机制内有效地表达他们的语言边界。CXX 填...

  • 1

    将 []T 切片转换为 []byte 类似C语言中将其他类型的数组转换为char数组: func ByteSlice(slice interface{}) (data []byte) { sv := reflect.ValueOf(slice) if sv.Kind() != reflect.Sl...

  • 9
    • blog.loli.fj.cn 1 year ago
    • Cache

    【笔记】ES5中新增的方法

    ES5中新增的方法 forEach()函数中的return不会终止循环 value:当前的遍历的值index:当前的遍历的索引this:数组本身 数组对象.forEac...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK