小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
而且一直以来,当谈到 JavaScript 语言,人们不会将其和模块系统联系起来。这是有其历史原因的,今天我们看一看 JavaScript 中的模块系统背后的故事。 首先回顾 JavaScript 模块系统一路走来。 了解历史这样有助于更好地学习模块,以了解今天的JavaScript模块是如何工作。
但在学习如何在 JavaScript 中创建模块之前,还是先来了解到底什么是模块,以及为什么需要模块。所以,现在就看看你的周围,通过身边一些熟悉事物帮助你了解什么是模块。任何能看到的复杂的项目都可能是用一个一个独立的部分所构成的。
以这只手表为例,现在看起来只是一块简单的手表,但是由数百个内部零件组成的。 每一个部件都有一个特定的用途或者说是功能,部件间有着明确的界限,以确定每一个部件与其他部件的互动方式。所有这些部件组合在一起,就构成了手表的整体。 即使对于不是一个钟表工程师的人,这种模块化方式好处是相不然而喻。
复用性
首先是可重复使用性,注意到在整个手表中使用了许多相同的部件。通过以模块化为中心的设计思想,能够在手表设计的不同方面(维度)地重复使用相同的部件。这种重复使用部件的能力简化了制造过程,同时会增加利润。
组合性
其次是可组合性,通过为每个独立的部件间有着明确的界限,能够将一些部件组合在一起,用部件创造出一个功能齐全的手表。
协作
接下来协作。想一想这块手表的制造过程。有的公司并不是在制造手表,而是在制造手表各个部件,这些部件在一起组成了手表。这些部件可以在公司内部制造,也可以将部件外包出去,由其他工厂协同来制造。
解耦合或者说独立组件
接下来是隔离,理解整个系统是很困难的。手表是由许多细化为独立运行的组件所组成的,这些部件中的每一个都可以被独立地设计、制造或修理。这种独立性允许多人协同工作,同时又不会使彼此的工作之间依赖关系,可以同时进行。
组织
最后是组织,组织只是每个单独的部件在与其他部件互动时,组织在一起具有一定功能。所以,我们已经看到了模块化的好处,
模块定义
就像手表的设计一样,我们应该把软件设计由部分所组成,每个部分都有特定的目的,并有明确的界限,以便与其他部分进行互动。在软件中,这些部分被称为模块。
所以,在这一点上,模块可能听起来与函数或 React 组件之类的东西没有太大区别,所以让看看模块到底包括什么。每个模块有三个不同的部分。首先导入部分,当一个模块需要另一个模块时,可以把那个模块作为依赖关系导入。例如,当你创建一个 react 组件时,需要导入 react 模块。
如果你想使用像 Lodash 这样的库,就需要导入 Lodash 模块。然后,确定的模块需要哪些导入或依赖后,下一部分就是实际的代码本身。
最后就是 export 。export 是模块的接口。无论从一个模块中导出什么,都会被导入该模块的人使用。好了,让我们看看一个实际生活中的模块的例子。这是来自React Router库,是他们的内存路由器模块。所以,注意到这里,有三件事要做。首先,这个模块定义了它的依赖关系,它导入了一些不同的东西。我们有 react、createMemoryHistory,然后是 router。
重用性
模块可以最大限度地提高重用性,因为一个模块可以被导入并用于任何需要的模块。除此之外,如果一个模块对另一个程序有益,可以把封装一个 package。package可以包含一个或多个模块,可以上传到像 npm 这样的服务,可以任何需要这个 package 的人都可以去下载。
这就是我们的 React、Lodash、jQuery,所有这些包的工作方式,如今是当你想 使用一个特定的库,你只需从 npm注册处下载该库,你就可以在你的代码中使用它。就可以在你的代码中使用它。
可组合性。
因为模块明确地定义了模块的输入和输出,可以很容易地组合,有点类似乐高。更重的是对于好的设计的软件,移除一部分代码也应该容易的,这样就要求模块间低耦合。
协作
已经谈论过这个问题了。npm 拥有世界上最大的免费可重用模块,超过70万个。需要一个特定功能的包,不必开发,npm已经有了。
index.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module" src="main.js"></script>
</body>
</html>
- 在 script 标签中需要添加
type="module"属性这样 JavaScript 文件就支持 ESM 模块 - 如果没添加
type="module"就会抛出下面这样异常
main.js:1 Uncaught SyntaxError: Cannot use import statement outside a module
tut.js
class Tut{
constructor(title,lesson){
this.title = title;
this.lesson = lesson
}
}
function printTitle(tut){
console.log(`title of tut: ${tut.title}`)
}
function printLesson(tut){
console.log(`title of tut: ${tut.lesson}`)
}
export default Tut;
导出方式有两种,其中一种为默认导出(export default) 而另外一种为标准导出
默认导出
export default Tut;
或者这样来定义为下面
export default class Tut{
constructor(title,lesson){
this.title = title;
this.lesson = lesson
}
}
标准导出
export {
printTitle,
printLesson
}
或者直接在函数表达式前添加 export
export function printTitle(tut){
console.log(`title of tut: ${tut.title}`)
}
export function printLesson(tut){
console.log(`title of tut: ${tut.lesson}`)
}
main.js
import Tut from './tut.js'
import Tut from './tut.js'
import { printTitle,printLesson } from './tut.js'
const tut = new Tut("machine learning",12);
printLesson(tut);
printTitle(tut);
我们可以直接导入默认导出 Tut 类,对于标准导出形式需要以这种方式 { printTitle,printLesson } 来进行导入
import Tutorial from './tut.js'
import { printTitle ,printLesson } from './tut.js'
const tut = new Tutorial("machine learning",12);
printLesson(tut);
printTitle(tut);
对于默认导出我们可以导入时对其进行命名为其他名称例如,Tutorial 而对于标准导出就需要通过 as 对导出内容起一个别名来调用该导出方法
import { printTitle as pTitle,printLesson } from './tut.js'
下一次我们分享一下 JavaScript 的模块。