From 0e57b52621c66060504335c0999409a7dfd6c898 Mon Sep 17 00:00:00 2001 From: LycheeEng Date: Mon, 3 Jun 2019 10:13:15 +0800 Subject: [PATCH 1/4] Translate 1-js/13-modules/01-modules-intro/article.md --- 1-js/13-modules/01-modules-intro/article.md | 381 ++++++++++++++++++ .../01-modules-intro/say.view/index.html | 6 + .../01-modules-intro/say.view/say.js | 3 + .../scopes-working.view/hello.js | 3 + .../scopes-working.view/index.html | 2 + .../scopes-working.view/user.js | 1 + .../01-modules-intro/scopes.view/hello.js | 1 + .../01-modules-intro/scopes.view/index.html | 3 + .../01-modules-intro/scopes.view/user.js | 1 + 9 files changed, 401 insertions(+) create mode 100755 1-js/13-modules/01-modules-intro/article.md create mode 100755 1-js/13-modules/01-modules-intro/say.view/index.html create mode 100755 1-js/13-modules/01-modules-intro/say.view/say.js create mode 100755 1-js/13-modules/01-modules-intro/scopes-working.view/hello.js create mode 100755 1-js/13-modules/01-modules-intro/scopes-working.view/index.html create mode 100755 1-js/13-modules/01-modules-intro/scopes-working.view/user.js create mode 100755 1-js/13-modules/01-modules-intro/scopes.view/hello.js create mode 100755 1-js/13-modules/01-modules-intro/scopes.view/index.html create mode 100755 1-js/13-modules/01-modules-intro/scopes.view/user.js diff --git a/1-js/13-modules/01-modules-intro/article.md b/1-js/13-modules/01-modules-intro/article.md new file mode 100755 index 0000000000..46f3277df5 --- /dev/null +++ b/1-js/13-modules/01-modules-intro/article.md @@ -0,0 +1,381 @@ +# 模块 (Modules) 简介 + +当我们的应用日益增大时,我们想要将应用分割成多个文件,即我们所说的“模块”。 + +一个模块通常包含一些有用的函数类或者库。 + +很长一段时间,JavaScript 都没有语言级(language-level)模块语法。这是因为初始的脚本都很小且简单,所以没必要将其模块化。 + +但是不管怎样,到最后,脚本文件都会变的越来越复杂,所以 JavaScript 社区发明了许多方法将代码组织为模块——一种特殊的可以按需加载的库。 + +例如: + +- [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition) -- 最古老的模块化系统,最开始应用在 [require.js](http://requirejs.org/) 这个库中。 + +- [CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1) -- 为 Node.js 创建的模块化系统。 + +- [UMD](https://github.com/umdjs/umd) -- 另外一个模块化系统,建议作为通用的模块化系统,它与 AMD 和 CommonJS 都是兼容的。 + +现在这些都将成为过去,但是我们仍然能在一些旧的脚本中找到他们的踪迹。语言级的模块化系统在 2015 年的时候出现在标准中,从那时候起开始逐渐发展,现在已经得到了所有主流浏览器和 Node.js 的支持。 + +## 什么是模块? + +模块仅仅是一个文件,一个脚本而已,它就是这么简单。 + +用一些关键字比如 `export` 和 `import` 来交换模块之间的功能(functionality)或者从一个模块中调用另一个模块中的函数。 + +- `export` 关键字表示在当前模块之外可以访问的变量和功能。 +- `import` 关键字允许从其他模块中导入一些诸如函数之类的功能等等。 + +例如,我们有一个名为 `sayHi.js` 的文件导出一个函数: + +```js +// 📁 sayHi.js +export function sayHi(user) { + alert(`Hello, ${user}!`); +} +``` + +然后在其他的文件里导入并使用它: + +```js +// 📁 main.js +import {sayHi} from './sayHi.js'; + +alert(sayHi); // function... +sayHi('John'); // Hello, John! +``` + +在这个章节里,我们专注于语言本身,但是我们使用浏览器作为演示环境,那么就让我们开始来看看怎么在浏览器中使用模块的。 + +由于模块使用特殊的关键词和功能,所以我们必须通过使用属性 ` +``` + +在这里我们可以在浏览器里看到它,但是对于任何模块来说都是一样的。 + +### 模块级作用域(Module-level scope) + +每个模块都有自己的顶级作用域(top-level scope)。换句话说,一个模块中的顶级作用域变量和函数在其他脚本中是不可见的。 + +在下面的这个例子中,我们导入了两个脚本,`hello.js` 尝试使用从 `user.js` 中导入的 `user` 变量。 + +[codetabs src="scopes" height="140" current="index.html"] + +模块可以导出 `export` 想要从外部访问的内容,也可以导入 `import` 想要的内容。 + +所以,我们应该在 `hello.js` 中直接导入 `user.js`,而不是在 `index.html` 中导入。 + +这是正确导入的方法: + +[codetabs src="scopes-working" height="140" current="hello.js"] + +在浏览器中,每个 ` + + +``` + +如果我们真的需要创建一个窗口级别(window-level)的全局变量,我们可以显式地将它分配给 `window` 并以 `window.user` 来访问它。但是这样做需要你有足够充分的理由,否则就不要这样。 + +### 模块代码仅在第一次导入时解析 + +如果将一个模块导入到多个其他位置,则仅在第一次导入时解析其代码,然后将导出提供给所有导入的位置。 + +这具有很重要的后果。我们来看一下下面的例子: + +首先,如果执行一个模块中的代码带来一些副作用,比如显示一个消息,然后多次导入它但是只会显示一次,即第一次: + +```js +// 📁 alert.js +alert("Module is evaluated!"); +``` + +```js +// 从不同的文件导入相同模块 + +// 📁 1.js +import `./alert.js`; // Module is evaluated! + +// 📁 2.js +import `./alert.js`; // (nothing) +``` + +在日常开发中,顶级模块主要是用于初始化使用的。我们创建数据结构,预填充它们,如果我们想要可重用某些东西,只要导出即可。 + +下面是一个高级点的例子: + +我们假设一个模块导出了一个对象: + +```js +// 📁 admin.js +export let admin = { + name: "John" +}; +``` + +如果这个模块是从多个文件中导入的,模块仅仅在第一次导入的时候解析创建 `admin` 对象。然后将其传入所有导入的位置。 + +所有导入位置都得到了唯一的 `admin` 对象。 + +```js +// 📁 1.js +import {admin} from './admin.js'; +admin.name = "Pete"; + +// 📁 2.js +import {admin} from './admin.js'; +alert(admin.name); // Pete + +*!* +// 1.js 和 2.js 导入相同的对象 +// 1.js 中对对象的修改,在 2.js 中是可访问的 +*/!* +``` + +所以,让我们重申一下:模块只执行一次。生成导出,然后在导入的位置共享同一个导出,当在某个位置修改了 `admin` 对象,在其他模块中是可以看到修改的。 + +这种行为对于需要配置的模块来说是非常棒的。我们可以在第一次导入时设置所需要的属性,然后在后面的导入中就可以直接使用了。 + +例如,下面的 `admin.js` 模块可能提供特定的功能,但是希望在外部可访问 `admin` 对象: + +```js +// 📁 admin.js +export let admin = { }; + +export function sayHi() { + alert(`Ready to serve, ${admin.name}!`); +} +``` + +现在,在 `init.js`——我们 app 的第一个脚本中,设置了 `admin.name`。现在每个位置都能看到它了,包括来自 `admin.js` 本身的调用。 + +```js +// 📁 init.js +import {admin} from './admin.js'; +admin.name = "Pete"; +``` + +```js +// 📁 other.js +import {admin, sayHi} from './admin.js'; + +alert(admin.name); // *!*Pete*/!* + +sayHi(); // Ready to serve, *!*Pete*/!*! +``` + +### import.meta + +`import.meta` 对象包含当前模块的一些信息。 + +它的内容取决于其所在环境,比如说在浏览器环境中,它包含脚本的链接,如果是在 HTML 中的话就是当前页面的链接。 + +```html run height=0 + +``` + +### 顶级 "this" 是 未定义(undefined) 的 + +这是一个小功能,但为了完整性,我们应该提到它。 + +在一个模块中,顶级 `this` 是未定义的,而不是像非模块脚本中的全局变量。 + +```html run height=0 + + + +``` + +## 特定于浏览器的功能 + +与常规脚本相比,拥有 `type =“module”` 标识的脚本有几个特定于浏览器的差异。 + +如果你是第一次阅读或者你不在浏览器中使用 JavaScript,你可能需要暂时略过这些内容。 + +### 模块脚本是延迟解析的 + +对于外部和内联模块脚本来说,它 *总是* 延迟解析的,就和 `defer` 属性一样(参见 [script-async-defer](info:script-async-defer))。 + +也就是说: + - 外部模块脚本 ` + +相较于普通脚本: + + + + +``` + +注意:上面的第二个脚本要先于前一个脚本执行,所以我们先会看到 `undefined`,然后才是 `object`。 + +这是因为模块脚本被延迟执行了,所以要等到页面加载结束才执行。而普通脚本就没有这个限制了,它会马上执行,所以我们先看到它的输出。 + +当使用模块脚本的时候,我们应该知道当 HTML 页面加载完毕的时候会显示出来,然后 JavaScript 在其后开始执行,所以用户会先于 JavaScript 脚本加载完成是看到页面内容。某些依赖于 JavaScript 的功能可能还不能正常工作。我们应该使用透明层或者 “加载指示”,或者其他方法以确保用户不会感到莫名其妙。 + +### 内联脚本是异步的 + +内联脚本和外部脚本都允许使用 ` +``` + +### 外部脚本 + +外部脚本相较于其他脚本有两个显著的差异: + +1. 具有相同 `src` 属性值的外部脚本仅运行一次: + ```html + + + + ``` + +2. 从其他域名获取的外部脚本需要加上 [CORS](mdn:Web/HTTP/CORS) 头。换句话说,如果一个模块脚本是从其他域名获取的,那么它所在的远端服务器必须提供 `Access-Control-Allow-Origin: *`(可能使用加载的域名代替 `*`) 响应头以指明当前请求是被允许的。 + ```html + + + + ``` + + 这可以保证最基本的安全问题。 + +### 不允许裸模块("bare" modules) + +在浏览器中,必须给与 `import` 一个相对或者绝对的 URL。没有给定路径的模块被称作 “裸” 模块。`import` 中不允许使用这些模块。 + +例如,下面这个 `import` 是不允许的: +```js +import {sayHi} from 'sayHi'; // Error, "裸" 模块 +// 模块必须提供路径, 例如 './sayHi.js' +``` + +在具体环境有所不同,比如 Node.js 或者打包工具中是可以使用裸模块的,因为它们有自己的查找模块和钩子的方法。但是目前浏览器还不支持裸模块。 + +### 兼容性,"nomodule" + +旧时的浏览器不理解 `type="module"` 值。对于位置类型的脚本会被忽略掉。对于它们来说可以使用 `nomodule` 属性来提供后备: + +```html run + + + +``` + +如果我们使用打包工具,当脚本被打包进一个单一文件(或者几个文件),在这些脚本中,`import/export` 语句被替换成特殊的打包函数。因此最终打包好的脚本不包含任何 `import/export` 语句,它也不需要 `type="module"` 属性,我们仅像普通脚本一样使用就好了: + +```html + + +``` + +## 构建工具 + +在日常开发中,浏览器模块很少以原始形式使用,通常,我们用一些特殊工具,像 [Webpack](https://webpack.js.org/),将他们打包在一起,然后部署到服务器。 + +使用打包工具的一个好处是——它们对于如何解析模块给与了足够多的控制,比如允许使用裸模块,以及 CSS/HTML 模块等等。 + +这里列出了一些构建工具做的事情: + +1. 从一个打算放在 HTML 中的 ` diff --git a/1-js/13-modules/01-modules-intro/say.view/say.js b/1-js/13-modules/01-modules-intro/say.view/say.js new file mode 100755 index 0000000000..198a3be6da --- /dev/null +++ b/1-js/13-modules/01-modules-intro/say.view/say.js @@ -0,0 +1,3 @@ +export function sayHi(user) { + return `Hello, ${user}!`; +} diff --git a/1-js/13-modules/01-modules-intro/scopes-working.view/hello.js b/1-js/13-modules/01-modules-intro/scopes-working.view/hello.js new file mode 100755 index 0000000000..6c087ea81a --- /dev/null +++ b/1-js/13-modules/01-modules-intro/scopes-working.view/hello.js @@ -0,0 +1,3 @@ +import {user} from './user.js'; + +document.body.innerHTML = user; // John diff --git a/1-js/13-modules/01-modules-intro/scopes-working.view/index.html b/1-js/13-modules/01-modules-intro/scopes-working.view/index.html new file mode 100755 index 0000000000..b78f759126 --- /dev/null +++ b/1-js/13-modules/01-modules-intro/scopes-working.view/index.html @@ -0,0 +1,2 @@ + + diff --git a/1-js/13-modules/01-modules-intro/scopes-working.view/user.js b/1-js/13-modules/01-modules-intro/scopes-working.view/user.js new file mode 100755 index 0000000000..d289329c61 --- /dev/null +++ b/1-js/13-modules/01-modules-intro/scopes-working.view/user.js @@ -0,0 +1 @@ +export let user = "John"; diff --git a/1-js/13-modules/01-modules-intro/scopes.view/hello.js b/1-js/13-modules/01-modules-intro/scopes.view/hello.js new file mode 100755 index 0000000000..714aafa1f1 --- /dev/null +++ b/1-js/13-modules/01-modules-intro/scopes.view/hello.js @@ -0,0 +1 @@ +alert(user); // no such variable (each module has independent variables) diff --git a/1-js/13-modules/01-modules-intro/scopes.view/index.html b/1-js/13-modules/01-modules-intro/scopes.view/index.html new file mode 100755 index 0000000000..a87e96fdfb --- /dev/null +++ b/1-js/13-modules/01-modules-intro/scopes.view/index.html @@ -0,0 +1,3 @@ + + + diff --git a/1-js/13-modules/01-modules-intro/scopes.view/user.js b/1-js/13-modules/01-modules-intro/scopes.view/user.js new file mode 100755 index 0000000000..12ec850d9a --- /dev/null +++ b/1-js/13-modules/01-modules-intro/scopes.view/user.js @@ -0,0 +1 @@ +let user = "John"; From 79276e4078f3857894fa95b6a82b0810fa550765 Mon Sep 17 00:00:00 2001 From: LycheeEng Date: Tue, 4 Jun 2019 10:30:41 +0800 Subject: [PATCH 2/4] Improved translation based on proof --- 1-js/13-modules/01-modules-intro/article.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/1-js/13-modules/01-modules-intro/article.md b/1-js/13-modules/01-modules-intro/article.md index 46f3277df5..bec787d5c2 100755 --- a/1-js/13-modules/01-modules-intro/article.md +++ b/1-js/13-modules/01-modules-intro/article.md @@ -62,7 +62,7 @@ sayHi('John'); // Hello, John! 下面有一些核心的功能,对于浏览器和服务端的 JavaScript 来说都是有效的。 -### 默认使用 "use strict" +### 始终使用 "use strict" 模块始终默认使用使用 `use strict`,例如,对一个未声明的变量赋值将会抛出错误。 @@ -143,7 +143,7 @@ export let admin = { }; ``` -如果这个模块是从多个文件中导入的,模块仅仅在第一次导入的时候解析创建 `admin` 对象。然后将其传入所有导入的位置。 +如果这个模块被导入到多个文件中,模块仅仅在第一次导入的时候解析创建 `admin` 对象。然后将其传入所有导入的位置。 所有导入位置都得到了唯一的 `admin` 对象。 @@ -269,7 +269,7 @@ sayHi(); // Ready to serve, *!*Pete*/!*! ### 内联脚本是异步的 -内联脚本和外部脚本都允许使用 ` ``` -如果我们使用打包工具,当脚本被打包进一个单一文件(或者几个文件),在这些脚本中,`import/export` 语句被替换成特殊的打包函数。因此最终打包好的脚本不包含任何 `import/export` 语句,它也不需要 `type="module"` 属性,我们仅像普通脚本一样使用就好了: +如果我们使用打包工具,当脚本被打包进一个单一文件(或者几个文件),在这些脚本中,`import/export` 语句被特殊的打包函数所替代。因此最终打包好的脚本不包含任何 `import/export` 语句,它也不需要 `type="module"` 属性,我们仅像普通脚本一样使用就好了: ```html @@ -350,14 +350,14 @@ import {sayHi} from 'sayHi'; // Error, "裸" 模块 这里列出了一些构建工具做的事情: 1. 从一个打算放在 HTML 中的 ` ``` -如果我们使用打包工具,当脚本被打包进一个单一文件(或者几个文件),在这些脚本中,`import/export` 语句被特殊的打包函数所替代。因此最终打包好的脚本不包含任何 `import/export` 语句,它也不需要 `type="module"` 属性,我们仅像普通脚本一样使用就好了: +如果我们使用打包工具,当脚本被打包进一个单一文件(或者几个文件),在这些脚本中,`import/export` 语句被特殊的打包函数处理后替代。因此最终打包好的脚本不包含任何 `import/export` 语句,它也不需要 `type="module"` 属性,我们仅像普通脚本一样使用就好了: ```html From 38f6abdfcc2241d487cd7a940f3a8cc425924886 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 4 Jun 2019 14:50:14 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=AF=91=E6=96=87?= =?UTF-8?q?=E7=BB=86=E8=8A=82=E6=A0=BC=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/13-modules/01-modules-intro/article.md | 58 ++++++++++----------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/1-js/13-modules/01-modules-intro/article.md b/1-js/13-modules/01-modules-intro/article.md index 694078955c..8535adb50b 100755 --- a/1-js/13-modules/01-modules-intro/article.md +++ b/1-js/13-modules/01-modules-intro/article.md @@ -1,20 +1,18 @@ + # 模块 (Modules) 简介 当我们的应用日益增大时,我们想要将应用分割成多个文件,即我们所说的“模块”。 - 一个模块通常包含一些有用的函数类或者库。 -很长一段时间,JavaScript 都没有语言级(language-level)模块语法。这是因为初始的脚本都很小且简单,所以没必要将其模块化。 +很长一段时间,JavaScript 都没有语言级(language-level)模块语法。这是因为初始的脚本都很小且简单,所以没必要将其模块化。 但是不管怎样,到最后,脚本文件都会变的越来越复杂,所以 JavaScript 社区发明了许多方法将代码组织为模块——一种特殊的可以按需加载的库。 例如: -- [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition) -- 最古老的模块化系统,最开始应用在 [require.js](http://requirejs.org/) 这个库中。 - -- [CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1) -- 为 Node.js 创建的模块化系统。 - -- [UMD](https://github.com/umdjs/umd) -- 另外一个模块化系统,建议作为通用的模块化系统,它与 AMD 和 CommonJS 都是兼容的。 +- [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition) — 最古老的模块化系统,最开始应用在 [require.js](http://requirejs.org/) 这个库中。 +- [CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1) — 为 Node.js 创建的模块化系统。 +- [UMD](https://github.com/umdjs/umd) — 另外一个模块化系统,建议作为通用的模块化系统,它与 AMD 和 CommonJS 都是兼容的。 现在这些都将成为过去,但是我们仍然能在一些旧的脚本中找到他们的踪迹。语言级的模块化系统在 2015 年的时候出现在标准中,从那时候起开始逐渐发展,现在已经得到了所有主流浏览器和 Node.js 的支持。 @@ -22,7 +20,7 @@ 模块仅仅是一个文件,一个脚本而已,它就是这么简单。 -用一些关键字比如 `export` 和 `import` 来交换模块之间的功能(functionality)或者从一个模块中调用另一个模块中的函数。 +用一些关键字比如 `export` 和 `import` 来交换模块之间的功能(functionality)或者从一个模块中调用另一个模块中的函数。 - `export` 关键字表示在当前模块之外可以访问的变量和功能。 - `import` 关键字允许从其他模块中导入一些诸如函数之类的功能等等。 @@ -74,9 +72,9 @@ sayHi('John'); // Hello, John! 在这里我们可以在浏览器里看到它,但是对于任何模块来说都是一样的。 -### 模块级作用域(Module-level scope) +### 模块级作用域(Module-level scope) -每个模块都有自己的顶级作用域(top-level scope)。换句话说,一个模块中的顶级作用域变量和函数在其他脚本中是不可见的。 +每个模块都有自己的顶级作用域(top-level scope)。换句话说,一个模块中的顶级作用域变量和函数在其他脚本中是不可见的。 在下面的这个例子中,我们导入了两个脚本,`hello.js` 尝试使用从 `user.js` 中导入的 `user` 变量。 @@ -105,7 +103,7 @@ sayHi('John'); // Hello, John! ``` -如果我们真的需要创建一个窗口级别(window-level)的全局变量,我们可以显式地将它分配给 `window` 并以 `window.user` 来访问它。但是这样做需要你有足够充分的理由,否则就不要这样。 +如果我们真的需要创建一个窗口级别(window-level)的全局变量,我们可以显式地将它分配给 `window` 并以 `window.user` 来访问它。但是这样做需要你有足够充分的理由,否则就不要这样。 ### 模块代码仅在第一次导入时解析 @@ -206,7 +204,7 @@ sayHi(); // Ready to serve, *!*Pete*/!*! ``` -### 顶级 "this" 是 未定义(undefined) 的 +### 顶级 "this" 是 未定义(undefined)的 这是一个小功能,但为了完整性,我们应该提到它。 @@ -224,27 +222,27 @@ sayHi(); // Ready to serve, *!*Pete*/!*! ## 特定于浏览器的功能 -与常规脚本相比,拥有 `type =“module”` 标识的脚本有几个特定于浏览器的差异。 +与常规脚本相比,拥有 `type="module"` 标识的脚本有几个特定于浏览器的差异。 如果你是第一次阅读或者你不在浏览器中使用 JavaScript,你可能需要暂时略过这些内容。 ### 模块脚本是延迟解析的 -对于外部和内联模块脚本来说,它 *总是* 延迟解析的,就和 `defer` 属性一样(参见 [script-async-defer](info:script-async-defer))。 +对于外部和内联模块脚本来说,它 **总是** 延迟解析的,就和 `defer` 属性一样(参见 [script-async-defer](info:script-async-defer))。 也就是说: - 外部模块脚本 ` @@ -253,7 +251,7 @@ sayHi(); // Ready to serve, *!*Pete*/!*! @@ -273,7 +271,7 @@ sayHi(); // Ready to serve, *!*Pete*/!*! 例如,下面的脚本中有 `async` 属性,所以它不会等待其他任何加载完成就已经开始运行。 -它导入(fetches `./analytics.js`)脚本,导入完成就开始运行,即使 HTML 文档还未解析完毕或者其他脚本仍在待处理的状态。 +它导入(fetches `./analytics.js`)脚本,导入完成就开始运行,即使 HTML 文档还未解析完毕或者其他脚本仍在待处理的状态。 这对于不依赖任何其他东西的功能来说是非常棒的,比如计数器,广告和文档级的事件监听器。 @@ -298,23 +296,23 @@ sayHi(); // Ready to serve, *!*Pete*/!*! ``` -2. 从其他域名获取的外部脚本需要加上 [CORS](mdn:Web/HTTP/CORS) 头。换句话说,如果一个模块脚本是从其他域名获取的,那么它所在的远端服务器必须提供 `Access-Control-Allow-Origin: *`(可能使用加载的域名代替 `*`) 响应头以指明当前请求是被允许的。 +2. 从其他域名获取的外部脚本需要加上 [CORS](mdn:Web/HTTP/CORS) 头。换句话说,如果一个模块脚本是从其他域名获取的,那么它所在的远端服务器必须提供 `Access-Control-Allow-Origin: *`(可能使用加载的域名代替 `*`)响应头以指明当前请求是被允许的。 ```html - + ``` 这可以保证最基本的安全问题。 -### 不允许裸模块("bare" modules) +### 不允许裸模块("bare" modules) -在浏览器中,必须给与 `import` 一个相对或者绝对的 URL。没有给定路径的模块被称作 “裸” 模块。`import` 中不允许使用这些模块。 +在浏览器中,必须给与 `import` 一个相对或者绝对的 URL。没有给定路径的模块被称作“裸”模块。`import` 中不允许使用这些模块。 例如,下面这个 `import` 是不允许的: ```js -import {sayHi} from 'sayHi'; // Error, "裸" 模块 -// 模块必须提供路径, 例如 './sayHi.js' +import {sayHi} from 'sayHi'; // Error,“裸”模块 +// 模块必须提供路径,例如 './sayHi.js' ``` 在具体环境有所不同,比如 Node.js 或者打包工具中是可以使用裸模块的,因为它们有自己的查找模块和钩子的方法。但是目前浏览器还不支持裸模块。 @@ -334,7 +332,7 @@ import {sayHi} from 'sayHi'; // Error, "裸" 模块 ``` -如果我们使用打包工具,当脚本被打包进一个单一文件(或者几个文件),在这些脚本中,`import/export` 语句被特殊的打包函数处理后替代。因此最终打包好的脚本不包含任何 `import/export` 语句,它也不需要 `type="module"` 属性,我们仅像普通脚本一样使用就好了: +如果我们使用打包工具,当脚本被打包进一个单一文件(或者几个文件),在这些脚本中,`import/export` 语句被特殊的打包函数处理后替代。因此最终打包好的脚本不包含任何 `import/export` 语句,它也不需要 `type="module"` 属性,我们仅像普通脚本一样使用就好了: ```html @@ -351,13 +349,13 @@ import {sayHi} from 'sayHi'; // Error, "裸" 模块 1. 从一个打算放在 HTML 中的 `