原文做者:Sébastien Castieljavascript
原文连接:Writing modern JavaScript codehtml
说点什么:这是一篇很朴素的文章,讲的道理都懂,但实际上,在工做中遇到相似的情形却未必如此,编写可维护,可阅读,更安全的代码是咱们应有的责任。前端
是否是还认为 JavaScript 是一门用于在光标悬浮时改变页面元素的语言?这些日子已经不复存在,每一种语言都在随着时间推移而发展,咱们使用语言的方式一样也在发展。看一下你一两年前写的代码:会感到羞愧吗?若是是的话,这篇文章应该很适合你。java
这里会列出一些所谓的最佳实践,目的是让你的 JavaScript 代码更容易编写,阅读和维护。react
第一个建议是使用 linter 工具,能够帮助你检查在不一样文件是否遵照一致的规则,尤为是当不一样开发人员在同一个项目上工做:缩进,括号中的空格,替换 ==
为 ===
...webpack
但更重要的是,尽量使用 linter 工具自动修复代码。ESLint 就作得很好(带有 --fix
选项),并且与全部主流 IDE 完美集成,能够在保存时自动修复文件。git
还可使用 Prettier,不过这款工具更注重格式化而不是静态检查,但处理后的结果基本相同。es6
下一步将介绍与 linter 工具一块儿使用的规则:github
若是不知道你的代码须要什么样的规则,能够参考:StandardJS。这是一个很是严格的 linter,没法修改配置,但里面的每一条规则已经愈来愈多地被社区接纳。好比:web
使用 2 个空格缩进(我曾经使用 4 个空格,但实际使用起来 2 个空格很不错)
不使用分号(一开始可能会以为奇怪,但几天后就再也回不去了)
在关键字(如 if)和花括号使用空格,在括号不使用空格
等等。
StandardJS 是一个独立的 Node 模块,能够进行 lint 和修复代码,但若是要在现有的大型项目中使用,而且想要停用一些规则(由于有些地方可能须要做大量修改),还可使用 ESLint 预约配置。好比,我就停用了规则 no-mixed-operators 和 import / no-webpack-loader-syntax。
若是你在使用 JavaScript 开发,根本没办法不据说 ES2015 +(或 ES6,ES7 ...)的特性。有的已是我离不开的:
箭头函数:对于函数式编程,好比写 x => x * 2
这样的函数很是有用(见下一点)
类:中止使用原型函数,使用类更酷炫(但不要滥用,JavaScript 比任何面向对象的语言好多了)
对数组和对象的操做:
function doSomething() { const a = doSomethingElse() const b = doSomethingWithA(a) const otherResults = { c: '?', d: '?' } return { a, b, ...otherResults } // equivalent to { a: a, b: b } } const { a, c, ...rest } = doSomething() // Also works with arrays! // `rest` looks like { b: ..., d: '?' }
使用 async/await
编写更简单的异步处理:
// Please try to write the same code with classic promises ;) async function doSomething() { const a = await getValueForA() const b = await getValueForBFromA(a) const [c, d] = await Promise.all([ // parallel execution getValueForC(), getValueForDFromB(b) ]) const total = await calculateTotal(a, b, c, d) return total / 1000 }
想知道如何使用这些特性呢?个人另外一篇文章能给一些建议。(顺便说一下,使用最新版本的 Node.js,可能再也不须要 Babel 就能使用这些新特性)
函数式编程最近很热门,取得很多成就,并且不只仅是在 JavaScript 中。为何呢?函数式编程能使代码更具可预测性,肯定性,更安全,一旦习惯这种方式,代码会更容易维护。这里有一些简单的建议:
首先,中止使用 for 循环,在大多数(多是全部?)状况下根本不须要。例如:
const arr = [{ name: 'first', value: 13 }, { name: 'second', value: 7 }] // Instead of: const res = {} for (let i = 0; i < arr.length; i++) { const calculatedValue = arr[i].value * 10 if (calculatedValue > 100) { res[arr[i].name] = calculatedValue } } // Prefer: const res = arr .map(elem => ({ name: elem.name, calculatedValue: elem.value * 10 })) .filter(elem => elem.calculatedValue > 100) .reduce((acc, elem) => ({ [elem.name]: elem.calculatedValue, ...acc }), {})
好吧,这其实是一个很是极端的例子,对于不习惯函数式编程的人而言,可能看起来更加复杂。但咱们能够稍微简化一下:
const enrichElementWithCalculatedValue = elem => ({ name: elem.name, calculatedValue: elem.value * 10 }) const filterElementsByValue = value => elem => elem.calculatedValue > value const aggregateElementInObject = (acc, elem) => ({ [elem.name]: elem.calculatedValue, ...acc }) const res = arr .map(enrichElementWithCalculatedValue) .filter(filterElementsByValue(100)) .reduce(aggregateElementInObject, {})
在这里,咱们定义了三个函数,其功能基本上与其名字一致。第二个建议:建立局部函数(即便是在已经存在的函数中)来讲明代码的功能,不须要使用注释。
注意,三个局部函数不修改它们的执行上下文。没有外部变量被修改,没有其余服务被调用...在函数式编程中,它们被称为纯函数。纯函数具备很大的优点:
很容易测试,由于从给定参数只有一个可能的结果,无论被调用了多少次;
不管应用状态如何,都能保证相同的结果;
应用状态在函数调用以前和以后保持不变。
因此个人第三个建议是:尽量地使用纯函数。
习惯于使用异步代码,并多使用 promise,看看 RxJS 的 observales(有一个很棒的教程关于从函数式编程到响应式编程)
写测试!这应该是很明显的,可是据我所知不少项目都有未经测试的代码,尽管测试 JavaScript(前端或后端)并不困难。
使用最新的语言特性:好比不要再写 arr.indexOf(elem) !== -1
,而应该写成 arr.includes(elem)
。
大量阅读技术文章:JavaScript subreddit 是了解目前社区最酷作法的一个很好的来源。
总而言之,最好的建议就是:老是重构你的代码。好比改进你一年前写过的模块?借此机会,用 const
取代 var
,使用箭头函数或 async/await
简化代码......和你喜欢的代码工做一件很愉悦的事。