"程序是写给人读的,只是偶尔让计算机执行一下." Donald Knuth
当你刚刚组建一个团队时,团队中的每个人都各自有一套编程习惯.毕竟,每个成员都有着不同的背景.有些人可能来自某个"皮包公司",身兼数职,在公司里面什么事都做;还有些人会来自不同的团队,对某种特定的做事风格情有独钟(或恨之入骨).每个人都觉得代码应当按照自己的想法来写,这些通常被归纳为个人编程嗜好.在这个过程中应当今早将统一的编程风格纳入议题.
以上来自于"编写可维护的javascript"一书的开头部分.
以下则是我认为可能需要摘捡出来便于记忆的一些.
1.1 换行
当一行长度达到了单行最大字符数限制时,就需要手动将一行拆成两行.通常我们会在用算符后换行,下一行会增加两个层级的缩进.比如(假定缩进为4个字符)
//运算符后换行,第二行追加两个缩进
callAFunction(document, element, window, 'some string value', true, 123,
navigator);
//语句换行
if(isLeapYear && isFebruary && day == 29 && itsYourBirthday &&
noPlans){
waitAnotherFourYears();
}
//列外: 变量赋值时,第二行的位置应当和赋值运算符的位置保持对齐
var result = something + anotherThing + yetAnotherThing + somethingElse +
anotherSomethingElse;
1.2 空行
空行是常常被忽略的一个方面.通常来讲,代码应该看起来像一系列可读的段落,而不是一大段揉在一起的连续文本.一段代码的语义和另一段不相关,这时就应该使用空行将它们分隔,
//没有加空行的代码段
if(wl && wl.length) {
for(var i = 0; i < wl.length; i++) {
p = wl[i];
type = Y.Lang.type(r[p]);
if(s.hasOwnProperty(p)) {
if(merge && type == 'object'){
Y.mix(r[p], s[p]);
}else if(ov || !(p in r)) {
r[p] = s[p];
}
}
}
}
//加入空行后
if(wl && wl.length) {
for(var i = 0; i < wl.length; i++) {
p = wl[i];
type = Y.Lang.type(r[p]);
if(s.hasOwnProperty(p)) {
if(merge && type == 'object'){
Y.mix(r[p], s[p]);
}else if(ov || !(p in r)) {
r[p] = s[p];
}
}
}
}
这段代码中是在每个流控制语句之前(比如if和for语句)添加空行.这样阅读起来更加流畅.
下面这些场景添加空行也是不错的.
- 在方法之间.
- 在方法中的局部变量(local variable)和第一条语句之间.
- 在多行或单行注释之前.
- 在方法内的逻辑片段之间插入空行,提高可读性.
1.3 命名
"计算机科学只存在两个难题: 缓存失效和命名." ----Phil Karlton.
ECMAScript遵照了驼峰式大小写命名法
//大驼峰
var ThisIsMyName;
//小驼峰
var thisIsMyName;
1.3.1 变量和函数
变量名遵循驼峰大小写命名法,并且命名前缀应当是名词
函数名前缀应为动词, 可以让变量和函数区分开来.
//好的写法
var count = 10;
var myName = 'Nicholas';
var found = true;
//不好的写法: 变量看起来像函数
var getCount = 10;
var isFound = true;
//好的写法
function getName() {
return myName;
}
//不好的写法: 函数看起来像变量
function theName() {
return myName;
}
命名不仅是一门科学, 更是一门技术. 命名长度尽可能短, 抓住要点. 尽量在变量名中提现出值得数据类型. 比如, 命名 count, length和size表明数据类型是数字, 而命名name, title, message表明是字符串等.
对于函数和方法命名来说,第一个单词应该是动词, 这里有一些常见的约定.
- can 返回一个布尔值
- has 返回一个布尔值
- is 返回一个布尔值
- get 返回一个非布尔值
- set 用来保存一个值
//这样可以使得代码可读性更强 这是一些例子
if(isEnabled()){
setName('Tony');
}
if(getName() === 'Tony'){
doSomething();
}
1.3.2 常量
通常使用大写字母和下划线来命名, 下划线用以分隔单词
const MAX_COUNT = 10;
1.3.3 构造函数
在js中,构造函数是加了new运算符的函数,用来创建对象. 需要用到大驼峰命名. 更好的区别是构造函数还是函数或者方法.
//好的做法
function Person(name) {
this.name = name;
}
Person.protopype.sayName = function() {
alert(this.name);
}
var me = new Person('Tony');
1.4 直接量
js中包含一些类型的原始值: 字符串, 数字, 布尔值, null和undefined. 同样也包含对象直接量和数组直接量.这其中,只有布尔是自解释的(self-explanatory)的,其他的类型或多或少都需要思考一下它们如何更精确的表示出来.
1.4.1 字符串
在js中,字符串是独一无二的.可以用双引号,也可以用单引号.你只需要将你的代码从头到尾保持一种风格即可. 比如我通常在html中用双引号,js中用单引号.
1.4.2 数字
数字类型只有一种,因为所有数字形式──整数和浮点数──都储存为相同的数据类型.还有一些其他的数字直接量格式来表示不同的数据格式.
//整数
var count = 10;
//小数
var price = 10.0;
var price = 10.00;
//不推荐写法
var price = 10.;
var price = .1;
1.4.3 null
null是一个特殊值,但我们常常误解它,将它和undefined搞混.在下列场景中使用null.
- 用来初始化一个变量,这个变量可能赋值为一个对象.
- 用来和一个已经初始化的变量比较,这个变量可以是也可以不是一个对象.
- 当函数的参数期望是对象时,用作参数传入.
- 当函数返回值期望是对象时,用作返回值传出.
还有下面一些场景不应当使用null.
- 不要使用null来检测是否传入了某个参数.
- 不要用null来检测一个未初始化的变量.
这里是一些代码示例.
//好的用法
var person = null;
//好的用法
function getPerson() {
if(condition) {
return new Person('Tony');
}else {
return null;
}
}
//好的用法
var person = getPerson();
if(person !== null) {
doSomething();
}
//不好的写法: 用来和未初始化的变量比较
var person;
if(person != null) {
doSomething();
}
//不好的写法: 检测是否传入了参数
function doSomething(arg1, arg2, arg3) {
if(arg3 != null) {
doSomethingElse();
}
}
理解null最好的方式是将它当做对象的占位符(placeholder).
1.4.4 undefined
undefined是一个特殊的值,我们常常将它和null搞混.其中一个让人困惑的地方在于null==undefined结果是true.然而,这两个值得用途各不相同.那些没有被初始化的变量都有一个初始值,即undefined,表示这个变量等待被赋值.比如:
//不好的写法
var person;
console.log(person === undefined); //true
尽管这段代码能正常工作,但是建议避免在代码中使用undefined.这个值常常和返回"undefined"的typeof运算符混淆.事实上,typeof的行为也很让人费解,因为不管是值是undefined的变量还是为声明的变量,typeof运算的结果都是"undefined".比如:
//foo未被声明
var person;
console.log(typeof person); //"undefined"
console.log(typeof foo); //"undefined"
这段代码中,person和foo都会导致typeof返回"undefined",即便是person和foo的其他场景中的行天差地别(在语句中使用foo会报错,而使用person则不会报错).
通过禁止使用特殊值undefined,可以有效地确保只在一种情况下typeof才会返回"undefined":当变量未声明时.如果你使用了一个可能(或可能不会)赋值为一个对象的变量时,则将其赋值为null.
//好的做法
var person = null;
console.log(person === null); //true
将变量初始赋值为null表明了这个变量的意图,它最终很可能赋值为对象.typeof运算符运算null的类型时返回"object",这样就可以和undefined区分开了.
1.4.5 对象直接量
创建对象最流行的一种做法是使用对象直接量,在直接量中直接写出所有属性.
对象直接量容许将所有的属性都括在一对花括号内.直接量可以高效的完成非直接量写法相同的任务,非直接量写法语法看起来更复杂一些.
//非直接量 不好的法
var book = new Object();
book.title = '编写可维护的js';
book.author = 'Nicholas';
//直接量 好的写法
var book = {
title: '编写可维护的js',
author: 'Nicholas'
}
1.4.6 数组直接量
和对象直接量类似,直接量是定义数组最简洁的一种方式.
//不好的写法 Array构造函数来创建数组
var colors = new Array('red', 'green', 'yellow');
var numbers = new Array(1, 2, 3, 4, 5);
//好的写法 数组直接量
var colors = ['red', 'green', 'yellow'];
var numbers = [1, 2, 3, 4, 5];
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。