在这篇文章中,我介绍了一些编程时尝试使用的模式。这些模式是多年来我自己在工作中实践的结果,也有是从同事那里偷偷学到的。
这些模式没有特定的顺序,只是一个简单的集合。
提前退出(early exits)
function transformData(rawData) {
// check if no data
if (!rawData) {
return [];
}
// check for specific case
if (rawData.length == 0) {
return [];
}
// actual function code goes here
return rawData.map((item) => item);
}
我将这种模式称为“提前退出(early exits)”,但有些人也将此称为“保镖模式(the Bouncer Pattern)”或“保护条款('guard clauses)”。撇开命名不谈,该模式采用的方法是首先检查无效的情况,然后从该函数返回,否则它将继续使用该函数的预期情况并执行。
对我来说,这种方法有一些我非常喜欢的优点:
- 有助于思考无效和边界情况,以及在这种情况下该如何处理。
- 避免对意外情况进行意外和不必要的代码处理
- 这样使我更能清楚地处理每种情况
- 一旦使用这种方式,您就可以快速地浏览函数并理解流程和执行,这通常遵循自顶向下的方法,即从无效的情况—>小情况—>预期情况。
更多信息:保镖模式(the Bouncer Pattern)
2. 用对象字面量替代 Switch
// Switch
let createType = null;
switch (contentType) {
case "post":
createType = () => console.log("creating a post...");
break;
case "video":
createType = () => console.log("creating a video...");
break;
default:
createType = () => console.log('unrecognized content type');
}
createType();
// Object literal
const contentTypes = {
post: () => console.log("creating a post..."),
video: () => console.log("creatinga video..."),
default: () => console.log('unrecognized content type')
};
const createType = contentTypes[contentType] || contentTypes['default'];
createType();
接下来就是要移除 Switch
。在写 case
的时候我经常会犯错误,也会忘记写 break
,这会引起各种有趣的问题。当我编写代码时,switch
语句并没有体现太多的价值。
我更喜欢使用对象字面量,原因如下:
- 不用担心
cace
或break
。 - 更容易阅读并快速了解正在发生的事情
- 对象字面量很容易写
- 代码量少
3. 用一次循环处理两个数组
const exampleValues = [2, 15, 8, 23, 1, 32];
const [truthyValues, falseyValues] = exampleValues.reduce((arrays, exampleValue) => {
if (exampleValue > 10) {
arrays[0].push(exampleValue);
return arrays;
}
arrays[1].push(exampleValue);
return arrays;
}, [[], []]);
这种模式没什么特别的,我应该早点意识到,但我发现自己过滤一组元素,以获得所有匹配特定条件的元素,然后在另一种情况下要再做一次。这意味着对一个数组进行两次循环,但我可以只做一次。
原来它有一个名字(bifurcate),我从 30secondsofcode.org借鉴过来的。如果你从未去过那个网站,我建议你去那里。有很多有用的信息和代码。
我知道 reduce
可能会让人望而生畏,也不太清楚会发生什么,但如果你能适应它,在遍历集合时,您可以真正利用它来构建所需的任何数据结构。他们应该叫它 builder
而不是 reduce
。
4. 不要用 foo
做变量
// bad
const foo = y && z;
// good
const isPostEnabled = isPost && postDateValid;
这看起来很明显,但我相信我们都见过这样做的代码。花点时间,尽你最大的努力取个合适的名字。
这对于在职的专业人士或处于教育他人位置的人来说尤其重要。应该使用变量命名来帮助解释,在代码的上下文中发生了什么事情。
别人能够在阅读您的代码时,并大致可以理解要解决的问题。
更多信息:The art of naming variables
5. 嵌套三元运算符
// 之前
let result = null;
if (conditionA) {
if (conditionB) {
result = "A & B";
} else {
result = "A";
}
} else {
result = "Not A";
}
// 改造后
const result = !conditionA
? "Not A"
: conditionB
? "A & B"
: "A";
我承认,一开始,使用嵌套三元运算符的想法的确令人倒胃口。它看起来是一种编写条件的巧妙方式。
然后我开始编写业务逻辑,发现自己使用了嵌套的 if else
语句和一些非常可疑的条件逻辑。
我认为使用 if
和 else
更容易阅读,因为它们是实际的单词,有语义化,但当它们嵌套后,我开始很难理解发生了什么,并在心里默默跟踪所有情况。
我认为这种模式取决于你、你的团队的偏好。我在代码库中也很好的使用这种方式。当然使用三元运算符具有两面性,但就我个人而言,嵌套三元运算符真的越来越吸引我了。