译:如何构造个人JavaScript文件?

前言

看到英文技术文档、快哭了。含着泪也要把他读完。 原文How I Structure My JavaScript Filejavascript

内容

不少人都在问我怎么写个人JavaScript——好吧,这是一个谎话,没人问我,可是若是他们这么作了,我想指出这篇文章。在使用了多年的PHP以后,在阅读了干净代码(和其余书籍)以后,我在多年中采用了个人代码风格。是的,PHP,不要敲它,它有一个伟大的社区和伟大的编码标准。固然,多年来和别人一块儿写做,跟随不一样公司的风格。java

结构并不依赖于JS模块,但我如今倾向于只编写JS模块,因此我将使用这些模块。数据库

结构,总结以下:浏览器

入口

在文件的顶部是导入。这是有道理的,他们比其余任何东西都要高。进口的顺序可有可无,除非你使用一些挂钩(好比babel hook),因此我倾向于选择:babel

  1. 本地模块-节点本地的东西。函数

  2. 库模块- lodash, knex,等等。工具

  3. 本地库——好比../db。测试

  4. 本地文件- like ./helper或相似的。fetch

让个人模块保持有序,让我更容易看到我在导入什么,以及我实际上在使用什么。当我开始编写代码时,我也倾向于以这种方式编写依赖关系。this

我倾向于不关心字母排序(除了破坏导入以外),我也没有看到它的一个点。

本地模块 我倾向于将本地模块放在最上面,并以这样的主题保持一个清晰的组织:

若是我在浏览器中,显然跳过这一步。

库模块

我尽量只从库中导入我须要的东西,可是,我又一次将它们分组到某个主题中。

我还注意到,若是我正在执行一个默认的导入(例如。我倾向于把它放在个人库模块的顶部,并将被破坏的导入下降。没有必要,但我喜欢它的视觉效果。

Local/Internal libraries

在本地库中,我指的是本地共享的模块,好比db。设置与书架链接的js文件。或者,在个人工做中,咱们有几个库处理咱们产品中使用的数字和计算。

Local files 最后,我导入本地文件,这些文件一般与我正在处理的文件或一个目录(最多)在同一个文件夹中。例如,我为Redux写了一个减速器,并把它放在一个单独的文件夹中。在该文件夹中,我还保留了一个助手文件,一般命名为[reducer name]Helpers.js:

Constants

在导入全部依赖项以后,我一般会作一些前期工做,这些工做将在模块的其他部分中使用。例如,我从书架实例中提取了knex。或者我能够设置值常数。

使用很是量一般表示我依赖于某种类型的单例。我尽可能避免使用它们,但有时它是必要的,由于没有简单的其余方法来完成它,或者它不重要(好比一次性命令行脚本)。 Exports

在我基本设置了全部模块级别的依赖项以后:不管它们是常量值仍是导入库,我都试着将个人导出分组到文件的顶部。基本上,这就是我把功能做为模块的粘合剂,实现模块的最终目的。

在Redux的状况下,我可能导出一个单一的减速器,而后将工做分解并调用相关的逻辑。在ExpressJS的状况下,我可能在这里导出全部的路由,而实际的路由逻辑在下面。

我想说的是,这并非我出口功能的惟一部分。

我感受模块系统的工做方式使得在暴露最窄的API和导出函数在测试中使用它们之间的界限变得有点困难。

例如,在上面的例子中,我历来不想在模块以外使用calculateSomething。我不彻底肯定OOP语言是如何处理测试私有函数的,但这是一个相似的问题。 Core Logic

这看起来很奇怪,但核心逻辑对我来讲是最重要的。我彻底理解当人们翻转导出和核心逻辑时,但这对我来讲颇有效,缘由有不少。

当我打开一个文件时,顶层函数会告诉我抽象步骤中将会发生什么。我很喜欢这样。我一眼就能看出文件的做用。我作了大量的CSV操做,并将其插入到DB中,而顶级函数始终是一个容易理解的流程,它有一个相似的流程:fetchCSV aggregateData insertData terminate script。

核心逻辑老是包括从上到下的出口。在内联的例子中,咱们有这样的东西:

注意,readCSV没有。这听起来很普通,我应该把它放到一个helper文件中,而后将它导入上面。除此以外,你能够看到个人出口,而不是进退两难。我不但愿在模块外部提供聚合数据,但我仍然但愿测试它。

在此以外,我倾向于把“meatier”函数放在上面,下面的函数更小。若是我有一个特定于模块的实用函数,一个我在多个地方使用的函数,但只在模块中使用,我将把它们放在底部。基本上,个人命令是:复杂性+使用。

因此顺序是:

  1. 核心逻辑函数——由顶级导出使用的函数。

  2. 更简单/更小的函数——核心逻辑函数使用的函数。

  3. 实用函数——模块周围多个地方使用的小函数(但不导出)

Core-logic functions 核心逻辑函数就像我导出的函数的“sub-glue”。根据模块的复杂性,这些可能存在,也可能不存在。功能的分解不是必需的,可是若是一个模块足够大,核心逻辑函数就像主函数中的步骤。

若是你写的是反应或角度,这些你的组件将是我上面提到的出口函数。可是,核心逻辑函数将是各类侦听器或数据处理器的实现。用Express,这些将是您的特定路线。在一个Redux减速器中,这些将是在链条上足够远的单独的减速器,没有一个开关/case语句。

若是您处于角度,那么在类中组织这些函数而不是在整个文件的范围内是彻底公平的。

Simpler/Smaller functions

这些函数一般是核心逻辑和纯实用程序之间的中间步骤。你可能会用到它们,或者它们可能只是一个比效用函数更复杂的tad。我可能会删除这个类别,并说“写你的功能,以减小复杂性或工做量”。

这里没有说起。也许onHandleInput事件监听器须要一些逻辑来处理$event数据,因此若是它是纯的,您能够将它从类中删除,若是不是,您能够在类中保留它:

Utility functions

最后,效用函数。我倾向于组织最接近我使用它们的工具。在相同的文件中,或者相同的文件夹(必要时),相同的模块,等等。每次使用从文件中扩展到项目的根或它本身的NPM模块时,我都将函数移出一个级别。

在我看来,效用函数应该始终是一种纯方法,这意味着它不该该在它的范围以外访问变量,并且应该只依赖传递到它的数据,并且不须要任何形式的反作用。除非使用实用程序函数来访问API或访问数据库。由于这些被认为是反作用,因此我认为它们是惟一的例外。

Anything else? 固然!我认为每一个人都有本身独特的书写方式。上面所描述的结构在我多年来天天编写大量代码的过程当中很是有效。最终,许多细微的差异开始出现,我发现本身编写代码更快,更喜欢它,而且更容易调试和测试。

在我完成这篇文章以前,我想和你们分享一些我已经习惯了的编码,它们与文档结构的关系更少,更多的是在编写实际代码时更倾向于使用小的偏好。

早期的回报

当我发现早期的回报时,那是一瞬间。当您能够提早返回时,为何要在else语句中封装大量代码?

个人经验法则是,若是早期的返回条件小于其他的代码,那么我将写早期的返回,可是若是不是,我将颠倒代码,这样较小的代码块老是提早返回。

早期的回报在交换机上也很出色,我是Redux的超级粉丝。

分号块

虽然我再也不使用它(没有更漂亮的支持),但我老是用分号来终止函数连接,在一个单独的行上,一个缩进到链的缩进的左边。这就建立了一个整洁的代码块,代码不仅是挂在那里。

固然,这意味着我也喜欢用分号来代替。

Or better written, it might look like this:

总结

使用的是有道在线翻译,若有不正确之处还望大佬指出。

相关文章
相关标签/搜索