使用ES2015模块,您可以将应用程序代码划分为可重用、封装的模块,专注于单个任务。那很好,但是你如何构建你的模块?一个模块应该有多少个函数和类?这篇文章描述了4个关于如何更好地组织JavaScript模块的最佳实践。1.首选命名导出当我开始使用JavaScript模块时,我使用默认语法导出单个模块定义块,无论是类还是函数。例如,这是一个将模块Greeter导出为默认值的模块程序:随着时间的推移,我注意到重构默认导出的类(或函数)的难度。重命名原始类时,消费者模块中的类名没有改变。更糟糕的是,编辑器没有为要导入的类名提供自动完成建议。我的结论是默认导出不会提供显着的好处。然后我继续进行命名导出。让我们将导出命名为Greeter,看看好处:使用命名导出,编辑器可以更好地重命名:每次更改原始类名时,所有消费者模块也会更改类名。自动完成还建议导入类:因此,这是我的建议:“支持命名模块导出以从重命名重构和代码自动完成中获益。”2.在模块级导入期间没有繁重的计算工作Scope定义了函数、类、对象和变量。该模块可以导出其中一些组件,就像这样。模块级作用域不应该像解析JSON、发出HTTP请求、读取本地存储等进行繁重的计算。例如,下面的模块配置从全局变量bigJsonString解析配置:这是一个问题,因为bigJsonString的解析是在模块级范围。bigJsonString的解析其实发生在配置模块导入的时候:在更高层次上,模块级作用域的作用是定义模块组件,导入依赖,导出公共组件:这就是依赖解析过程。它应该与运行时分离:解析JSON、发出请求、处理事件。让我们重构配置模块来执行惰性解析:由于data属性被定义为一个getter,bigJsonString只有在消费者访问configuration.data时才会被解析。消费者更清楚何时执行大型操作,并且用户可能决定在浏览器空闲时执行操作。或者,消费者可能会导入一个模块,但由于某种原因不使用它。这为更深入的性能优化开辟了机会:减少交互时间并最大限度地减少主线程工作。模块在导入时不应执行任何繁重的工作。相反,消费者应该决定何时执行运行时操作。3、尽量使用高内聚。模块内聚性描述了模块内各个组件在一起的程度。高内聚模块的函数、类或变量密切相关,它们专注于单一任务。formatDate模块是高度内聚的,因为它的功能密切相关并专注于日期格式化:formatDate()、ensureDateInstance()和MONTHS彼此密切相关。删除MONTHS或ensureDateInstance()会破坏formatDate():这是高内聚的标志。4.避免过长的相对路径我发现很难理解一个模块的路径包含一个甚至多个父文件夹:虽然有一个父选择器../通常不是问题,但有2个或更多通常很难掌握。这就是为什么我建议避免使用父文件夹并使用绝对路径的原因:虽然有时写绝对路径需要更长的时间,但使用绝对路径可以明确导入模块所在的位置。为了减少冗长的绝对路径,可以引入一个新的根目录。例如,这可以使用babel-plugin-module-resolver来实现。使用绝对路径而不是长的相对路径。5.结论JavaScript模块非常适合将应用程序逻辑分解成更小、独立的部分。通过使用命名导出而不是默认导出来导入命名组件时,更容易重命名重构和编辑器自动完成帮助。使用import{myFunc}from'myModule'的唯一目的是导入myFunc组件,仅此而已。myModule的模块级作用域应该只定义包含少量内容的类、函数或变量。一个组件应该有多少个函数或类,这些函数或类应该如何与每个组件相关联?支持高内聚的模块:它的组件应该密切相关并执行共同的任务。有很多父文件夹的长相对路径../很难理解,将它们重构为绝对路径。
