软件bug的修复是昂贵的,而且随着时间的推移,这些bug的成本也会增长,尤为当这些bug潜伏并慢慢出如今已经发布的软件中时。当你发现bug 的时候就当即修复它是最好的,此时你代码要解决的问题在你脑中仍是很清晰的。不然,你转移到其余任务,忘了那个特定的代码,一段时间后再去查看这些代码就 须要:javascript
另外一个相关软件开发生命的事实是,读代码花费的时间要比写来得多。有时候,当你专一并深刻思考某个问题的时候,你能够坐下来,一个下午写大量的代码。css
你的代码很能很快就工做了,可是,随着应用的成熟,还会有不少其余的事情发生,这就要求你的进行进行审查,修改,和调整。例如:html
因为这些变化,不多人力数小时写的代码最终演变成花数周来阅读这些代码。这就是为何建立可维护的代码对应用程序的成功相当重要。java
可维护的代码意味着:
提示: 不遵照这些原则代码也能运行起来。只是可能出现难以维护的现象。规范就像一种模式,你们按照一种模式来,那么阅读其余人的代码,成本就下降了。git
function func() { var a = 1, b = 2, sum = a + b, myobject = {}, i, j; // function body... }
注意:在es6中,使用let 定义,可能出现'暂时性死区', 具体想知道什么叫作'暂时性死区' , 请查看阮一峰 ECMAScript 6 入门es6
// 次佳的循环 for (var i = 0; i < myarray.length; i++) { // 使用myarray[i]作点什么 } //更好的方式 for (var i = 0, max = myarray.length; i < max; i++) { // 使用myarray[i]作点什么 }
**JSLint提示您这样作,缘由是++和–-促进了“过度棘手(excessive trickiness)”。//zxx:这里比较难翻译,我想本意应该是让代码变得更加的棘手
若是你直接无视它,JSLint的plusplus选项会是false(默认是default)。**github
还有两种变化的形式,其又有了些微改进,由于:正则表达式
//第一种变化的形式:
var i, myarray = [];
for (i = myarray.length; i–-;) {
// 使用myarray[i]作点什么
}api
//第二种使用while循环:数组
var myarray = [],
i = myarray.length;
while (i–-) {
// 使用myarray[i]作点什么
}
面两种状况优于前面两种状况。
for-in循环应该用在非数组对象的遍历上,使用for-in进行循环也被称为“枚举”。
从技术上将,你可使用for-in循环数组(由于JavaScript中数组也是对象),但这是不推荐的。由于若是数组对象已被自定义的功能加强,就可能发生逻辑错误。另外,在for-in中,属性列表的顺序(序列)是不能保证的。因此最好数组使用正常的for循环,对象使用for-in循环。
有个很重要的hasOwnProperty()方法,当遍历对象属性的时候能够过滤掉从原型链上下来的属性
// 对象 var man = { hands: 2, legs: 2, heads: 1 }; // 在代码的某个地方 // 一个方法添加给了全部对象 if (typeof Object.prototype.clone === "undefined") { Object.prototype.clone = function () {}; } ==================================================================== // for-in 循环 for (var i in man) { if (man.hasOwnProperty(i)) { // 过滤 console.log(i, ":", man[i]); } } /* 控制台显示结果 hands : 2 legs : 2 heads : 1 */ ========================================================================== // 反面例子: // for-in loop without checking hasOwnProperty() for (var i in man) { console.log(i, ":", man[i]); } /* 控制台显示结果 hands : 2 legs : 2 heads : 1 clone: function() */
增长内置的构造函数原型(如Object(), Array(), 或Function())挺诱人的,可是这严重下降了可维护性,由于它让你的代码变得难以预测。使用你代码的其余开发人员极可能更指望使用内置的 JavaScript方法来持续不断地工做,而不是你另加的方法。
所以,不增长内置原型是最好的。你能够指定一个规则,仅当下面的条件均知足时例外:
你清楚地文档记录并和团队交流了变化。
if (typeof Object.protoype.myMethod !== "function") { Object.protoype.myMethod = function () { // 实现... }; }
通常状况下,强烈不建议使用
JavaScript的变量在比较的时候会隐式类型转换。这就是为何一些诸如:false == 0 或 “” == 0 返回的结果是true。为避免引发混乱的隐含类型转换,在你比较值和表达式类型的时候始终使用===和!==操做符。
var zero = 0; if (zero === false) { // 不执行,由于zero为0, 而不是false } // 反面示例 if (zero == false) { // 执行了... }
若是你如今的代码中使用了eval(),记住该咒语“eval()是魔鬼”。此方法接受任意的字符串,并看成JavaScript代码来处理。当有 问题的代码是事先知道的(不是运行时肯定的),没有理由使用eval()。若是代码是在运行时动态生成,有一个更好的方式不使用eval而达到一样的目 标。例如,用方括号表示法来访问动态属性会更好更简单:
// 反面示例 var property = "name"; alert(eval("obj." + property)); // 更好的 var property = "name"; alert(obj[property]);
代码没有缩进基本上就不能读了。惟一糟糕的事情就是不一致的缩进,由于它看上去像是遵循了规范,可是可能一路上伴随着混乱和惊奇。重要的是规范地使用缩进。
一些开发人员更喜欢用tab制表符缩进,由于任何人均可以调整他们的编辑器以本身喜欢的空格数来显示Tab。有些人喜欢空格——一般四个,这都无所谓,只要团队每一个人都遵循同一个规范就行了。这本书,例如,使用四个空格缩进,这也是JSLint中默认的缩进。
什么应该缩进呢?规则很简单——花括号里面的东西。这就意味着函数体,循环 (do, while, for, for-in),if,switch,以及对象字面量中的对象属性。下面的代码就是使用缩进的示例:
function outer(a, b) { var c = 1, d = 2, inner; if (a > b) { inner = function () { return { r: c - d }; }; } else { inner = function () { return { r: c + d }; }; } return inner; }
// 糟糕的实例 for (var i = 0; i < 10; i += 1) alert(i); // 好的实例 for (var i = 0; i < 10; i += 1) { alert(i); }
这个实例中,仁者见仁智者见智,但也有个案,括号位置不一样会有不一样的行为表现。这是由于分号插入机制(semicolon insertion mechanism)——JavaScript是不挑剔的,当你选择不使用分号结束一行代码时JavaScript会本身帮你补上。这种行为可能会致使麻 烦,如当你返回对象字面量,而左括号却在下一行的时候
// 警告: 意外的返回值 function func() { return // 下面代码不执行 { name : "Batman" } } // 警告: 意外的返回值 function func() { return undefined; // 下面代码不执行 { name : "Batman" } }
空格的使用一样有助于改善代码的可读性和一致性。在写英文句子的时候,在逗号和句号后面会使用间隔。在JavaScript中,你能够按照一样的逻辑在列表模样表达式(至关于逗号)和结束语句(相对于完成了“想法”)后面添加间隔。
适合使用空格的地方包括:
使用空格分开全部的操做符和操做对象是另外一个不错的使用,这意味着在+, -, *, =, <, >, <=, >=, ===, !==, &&, ||, +=等先后都须要空格。
// 宽松一致的间距 // 使代码更易读 // 使得更加“透气” var d = 0, a = b + 1; if (a && b && c) { d = a % c; a += d; } // 反面例子 // 缺失或间距不一 // 使代码变得疑惑 var d = 0, a = b + 1; if (a&&b&&c) { d=a % c; a+= d; }
最后须要注意的一个空格——花括号间距。最好使用空格:
//{} 空格
if (4) {
console.log(1)
} else if (3) {
console.log(1)
}
var a = {}
JavaScript并无类,但有new调用的构造函数:
var adam = new Person();
由于构造函数仍仅仅是函数,仅看函数名就能够帮助告诉你这应该是一个构造函数仍是一个正常的函数。
命名构造函数时首字母大写具备暗示做用,使用小写命名的函数和方法不该该使用new调用:
function MyConstructor() {...} function myFunction() {...}、
当你的变量或是函数名有多个单词的时候,最好单词的分离遵循统一的规范,有一个常见的作法被称做“驼峰(Camel)命名法”,就是单词小写,每一个单词的首字母大写。
## 4.3 注释(Writing Comments)
你必须注释你的代码,即便不会有其余人向你同样接触它。一般,当你深刻研究一个问题,你会很清楚的知道这个代码是干吗用的,可是,当你一周以后再回来看的时候,想必也要耗掉很多脑细胞去搞明白到底怎么工做的。很显然,注释不能走极端:每一个单独变量或是单独一行。可是,你一般应该记录全部的函数,它们的参数和返回值,或是任何不寻常的技术和方法。要想到注 释能够给你代码将来的阅读者以诸多提示;阅读者须要的是(不要读太多的东西)仅注释和函数属性名来理解你的代码。例如,当你有五六行程序执行特定的任务, 若是你提供了一行代码目的以及为何在这里的描述的话,阅读者就能够直接跳过这段细节。没有硬性规定注释代码比,代码的某些部分(如正则表达式)可能注释 要比代码多。
css规范咱们伟大的张旭鑫老师,讲的很清楚。面向属性的命名
这是比较好的命名规范。简介来讲,就是咱们先定义好一些经常使用基础类样式。组件则使用less,或者sass进行组装,造成便可。