一、模块化的背景和目的
- 模块化的背景
- 代码重复:功能类似的代码在多个地方出现,导致维护成本增加。
- 耦合度高:代码之间依赖性强,修改一个地方可能会导致其他部分出现问题。
- 难以扩展:想要新增功能时,现有代码结构复杂,改动需要冒高风险。
- 模块化的目的:
- 方便维护:模块化可以使代码结构更加清晰。开发者可以专注于维护单个模块,而不用担心整个项目的复杂性。
- 可重用性:一个模块可以在不同的项目或同一项目的多个地方使用,减少重复代码。
- 提高可读性和可测试性:由于每个模块的功能通常是单一的,代码更易于理解和测试,模块化的代码也更容易进行单元测试。
- 隔离性:模块之间相互独立,一个模块的更改不会直接影响到其他模块,减少了副作用。
- 团队协作:在大型项目中,模块化可以让多个开发者并行工作,各自负责不同的模块,从而提高开发效率。
二、模块化的原则
-
单一职责原则(Single Responsibility Principle, SRP)
每个模块应仅负责一个特定的功能或任务。这使得模块更易于理解和维护,同时减少了不同功能之间的耦合。 -
开放-关闭原则(Open/Closed Principle, OCP)
模块应该对扩展开放,对修改关闭。这意味着可以通过增加新功能而不是更改现有代码来扩展模块,从而降低风险。 -
里氏替换原则(Liskov Substitution Principle, LSP)
子类应该可以替换父类而不影响程序的正确性。确保模块能够以一致的方式工作,可以提高代码的灵活性和可重用性。 -
接口隔离原则(Interface Segregation Principle, ISP)
模块应依赖于最小的接口,而不是一个大的接口。这样可以避免不必要的依赖,提高模块的灵活性。 -
依赖倒置原则(Dependency Inversion Principle, DIP)
高层模块不应依赖于低层模块,两者应依赖于抽象。通过依赖注入等方式,可以减少模块之间的耦合性,提高可测试性和灵活性。
三、 import
和export
的用法
export
的几种用法- 命名导出1:在需要导出的变量/函数/对象前使用
export
关键字export const num=1;
export function func(){...};
- 等等
- 命名导出2:在最后一行使用
export
统一导出所有需要导出的变量/函数/对象const num =1;
function func(){...};
export {num, func};
- 默认导出1:
export default function(){...}
- 默认导出2:
function func(){...}
;export default func;
- 命名导出1:在需要导出的变量/函数/对象前使用
import
的几种用法- 命名导入(对应命名导出):
import { 导出名1, 导出名2, ...} from "被导出文件位置"
- 默认导入(对应默认导出):
import{ 自定义导入名 } from "被导出文件位置"
- 命名空间导入:
import * as 自定义类名 from "被导出文件位置";
(导出被绑定在了这个自定义类名上,as是重命名语法) - 副作用导入:
import "被导出文件位置"
- 命名导入(对应命名导出):
- 注意事项:
- 只能在模块内部使用
import/export
,<script type='module'>
- 本地测试时,模块需要启动服务器才能正常工作
- 模块自动启动严格模式
- 加载模块脚本无需defer,模块会自动延迟加载
- 只能在模块内部使用
- 动态加载模块
import("/modules/mymodule.js").then((module) => { // Do something with the module. });
- 可以需要时动态加载模块,而不必预先加载所有模块,具有性能优势。