电脑程序是人类制造出来的最复杂的玩意儿。程序通常由很多部分组成,表现为函数、语句和表达式,它们必须准确无误的按照顺序排列。
运行时行为几乎和实现它的程序没有什么相似之处。在软件的产品生命周期中,通常它们都会被修改。把一个正确的程序转化为另一个同样正确但风格不同的程序,是一个极具挑战性的过程。
优秀的程序拥有一个前瞻性的结构,它会预见未来所需要的可能修改,但不会让其成为过度的负担。
优秀的程序也有一种清晰的表达式,如果一个程序表达的很好,那么我们就能更加容易地去理解它,以便成功地修改或修复它。
这些观点适用于所有的编程语言,且对 JavaScript 来说尤其正确。JavaScript 的弱类型和过度的容错并没有给程序质量带来什么编译时的保证,所以为了弥补,我们应该按照严格的规范来进行编码。
JavaScript 包含了大量脆弱且有问题的特性,它们会妨碍我们写出优秀的代码。显然我们应该避免 JavaScript 所有糟糕的特性。令人惊讶的是,我们也应该避免那些通常很有用但偶尔有害的特性,这样的特性让人又爱又恨。然而,通过避免它们,可以避免一系列潜在的问题。
对于一个组织机构来说,软件的长期价值是和代码库的质量成正比的。在程序的生命周期里,会经历很多人的检测、使用和修改。如果一个程序能很清楚地传达它的结构和特性,那么当它在并不遥远的未来被修改的时候,它被破坏的可能性就会小很多。
JavaScript 代码经常被直接发布,它应该自始至终具备发布质量,整洁是会带来价值的。通过二一个清晰且始终如一的风格编写,你的程序会变得易于阅读。
程序员会无休止地讨论良好的风格是由什么构成的。大多数程序员会坚定地植根于他们过去是怎么用的,诸如他们在学校或第一份工作时学到的最普遍的风格。他们中有一些人拥有高薪的工作,但完全没有代码风格的意识。这是不是证明了风格不重要呢?即使风格重要,是不是说某个风格就不如另一个风格呢?
事实证明代码风格在编程中是重要的,就像文字风格对于写作是重要的一样。好的风格能促进代码被更好的阅读。
电脑程序有时候被认为是不需要读的媒介,它只需要工作,写成什么样是不重要的。但是结果证明,如果程序具有可读性,将显著增加它正常运行的可能性,以及是否准确按照我们的意图去工作的可能性。它也决定了软件在其生命周期中是否进行扩展性修改。如果我们能阅读并且理解程序,那么我们就有希望去提高和修改它。
始终采用一致的风格,目的是代码尽可能地易于阅读,并始终用空白来给程序更多的提示。
我对代码块内容和对象字面量缩进 4 个空格,并且放了一个空格在 if 和 ( 之间,以至于 if 不会看起来像一个函数调用。只有真的在调用的时候,我才使 ( 和前面的符号相连。我在除了 . 和 [ 外的所有中置运算符的两边都放了空格,它们两无需空格是因为它们有更高的优先极,我在每个逗号和冒号后面都使用了一个空格。
每行最多放一个语句,在一行里放多个语句可能会被误读。如果一个语句一行放不下,我将在一个冒号或者二元运算符后拆开它。这将更好地防止复制粘贴的错误被自动插入分号的机制所掩盖。
始终在结构化的语句中使用代码块,例如 If 和 while,因为这样会减少出错的几率,我曾看到过:
if(a)
b()
变成
if(a)
b()
c()
这是一个很难被发现的错误,它看起来像是
if(a){
b()
c()
}
但它的本意是
if(a){
b()
}
c()
看起来想要做一件事,但实际上却在做另外一件事的代码可能会导致 bug。一对花括号可以用很低廉的成本去防止那些需要昂贵成本才能发现的 bug。
我一直使用 K&R 风格,把 { 放在一行的结尾,而不是下一行的开头,因为它会避免在 JavaScript 的 return 语句中一个可怕的设计错误。
我的代码包含了一些注释,我喜欢在程序中放入注释来留下一些信息,以后,它将会被那些需要理解我当时的思路的人(也可能是自己)阅读。有时候注释就像是一个时间机器,我用它发送重要的信息给未来的我自己。
我努力保持注释是最新的,错误的注释甚至可能会使程序更加难以阅读和理解。我不能容忍那样的错误。
尽量不要用无用的注释去浪费你的时间
i=0//设置i为0
在 JavaScript 中,我更喜欢用行注释,我将块注释用与正式的文档记录和注释。
我更喜欢使我的程序结构具备自我启发性,从而消除对注释的需要。并非每次都能成功,所以只要我的程序还没有圆满,我就会编写注释。
JavaScript 语言拥有 C 语言的语法,但它的代码块没有作用域,所以,在 JavaScript 中,变量在它们第一次使用时被声明是个糟糕的建议。JavaScript 有函数所有域,但是没有块级作用域,所以我在每个函数的开始部分声明我所有的变量。JavaScript 允许变量在它们使用后被声明,那对我来说感觉像是一个错误。我希望我的错误被突显出来,相似地,我绝不在一个 if 的条件部分使用赋值表达式,因为:
if(a=b){}
可能的本意是:
if(a===b){}
我想要避免那些看起来像是有错误的惯用法。
我绝不允许 switch 语句块中的条件贯穿到下一个 case 语句。我曾经在我的代码里发现了一个无意识的「贯穿」而导致的 bug。
能够从经验中学习,我觉得非常的幸运,当我现在评审一门语言的特性的时候,我把注意力放在那些有时很有用,但偶尔很危险的特性上,那些是最糟糕的部分,因为我们很难辨别它们是否被正确的使用了。那是 bug 的藏身之地。
在 JavaScript 的设计、实现标准化的过程中,质量没有成为关注点。这增加使用这门语言的用户避免其缺陷的难度。
JavaScript 为大型程序提供了支持,但它也提供了不利于大型程序的形式和惯用法。举例来说:JavaScript 为全局变量提供了方便,但随着程序的日益复杂,全局变量逐渐变得问题重重。
我用一个单独的全局变量去包含一个脚本应用或工具库,每个对象都有它自己的命名空间,所以我很容易使用对象去管理代码。闭包的使用提供了进一步的信息隐藏,增强了我的模块。
,