由于受限于 CORS 策略,必须在服务器环境中使用模块,否则会出现下面的错误:
Access to script at 'file:///Users/your_file_path/script.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
模块与常规脚本不一样的地方:
- 模块不会向全局(
window
)作用域添加任何内容。 - 模块始终处于严格模式。
- 在同一文件中把同一模块加载两次不会出问题,因为模块仅执行一次
- 模块需要服务器环境。
模块仍然经常与打包程序(如 Webpack)一起配合使用,用来增加对浏览器的支持和附加功能,但它们也可以直接用在浏览器中。
接下来探索更多使用 import
和 export
语法的方式。
命名导出
如前所述,使用 export
语法允许你分别导入按名称导出的值。以这个 function.js
的简化版本为例:
functions.js
export function sum() {}
export function difference() {}
这样允许你用花括号按名称导入 sum
和 difference
:
script.js
import {sum, difference} from './functions.js'
也可以用别名来重命名该函数。这样可以避免在同一模块中产生命名冲突。在这个例子中,sum
将重命名为 add
,而 difference
将重命名为 subtract
。
script.js
import {
sum as add,
difference as subtract
} from './functions.js'
add(1, 2) // 3
在这里调用 add()
将产生 sum()
函数的结果。
使用 *
语法可以将整个模块的内容导入到一个对象中。在这种情况下,sum
和 difference
将成为 mathFunctions
对象上的方法。
script.js
import * as mathFunctions from './functions.js'
mathFunctions.sum(1, 2) // 3
mathFunctions.difference(10, 3) // 7
原始值、函数表达式和定义、异步函数、类和实例化的类都可以导出,只要它们有标识符就行:
// 原始值
export const number = 100
export const string = 'string'
export const undef = undefined
export const empty = null
export const obj = {name: 'Homer'}
export const array = ['Bart', 'Lisa', 'Maggie']
// 函数表达式
export const sum = (x, y) => x + y
// 函数定义
export function difference(x, y) {
return x - y
}
// 匿名函数
export async function getBooks() {}
// 类
export class Book {
constructor(name, author) {
this.name = name
this.author = author
}
}
// 实例化类
export const book = new Book('Lord of the Rings', 'J. R. R. Tolkein')
所有这些导出都可以成功被导入。接下来要探讨的另一种导出类型称为默认导出。
默认导出
在前面的例子中我们导出了多个命名的导出,并分别或作为一个对象导入了每个导出,将每个导出作为对象上的方法。模块也可以用关键字 default
包含默认导出。默认导出不使用大括号导入,而是直接导入到命名标识符中。
以 functions.js
文件为例:
functions.js
export default function sum(x, y) {
return x + y
}
在 script.js
文件中,可以用以下命令将默认函数导入为 sum
:
script.js
import sum from './functions.js'
sum(1, 2) // 3
不过这样做很危险,因为在导入过程中对默认导出的命名没有做任何限制。在这个例子中,默认函数被导入为 difference
,尽管它实际上是 sum
函数:
script.js
import difference from './functions.js'
difference(1, 2) // 3
所以一般首选使用命名导出。与命名导出不同,默认导出不需要标识符——原始值本身或匿名函数都可以用作默认导出。以下是用作默认导出的对象的示例:
functions.js
export default {
name: 'Lord of the Rings',
author: 'J. R. R. Tolkein',
}
可以用以下命令将其作为 book
导入:
functions.js
import book from './functions.js'
同样,下面的例子演示了如何将匿名箭头函数导出为默认导出:
functions.js
export default () => 'This function is anonymous'
可以这样导入:
script.js
import anonymousFunction from './functions.js'
命名导出和默认导出可以彼此并用,例如在这个模块中,导出两个命名值和一个默认值:
functions.js
export const length = 10
export const width = 5
export default function perimeter(x, y) {
return 2 * (x + y)
}
可以用以下命令导入这些变量和默认函数:
script.js
import calculatePerimeter, {length, width} from './functions.js'
calculatePerimeter(length, width) // 30
现在默认值和命名值都可用于脚本了。
总结
模块化编程设计允许我们把代码分成单个组件,这有助于代码重用,同时还可以保护全局命名空间。一个模块接口可以在原生 Javascript 中用关键字 import
和 export
来实现。
以上就是一起看看 Javascript 中的模块、Import和Export的详细内容,更多请关注其它相关文章!