基本的格式化
命名
“计算机科学只存在两个难题:缓存失效和命名。”—— Phil Karlton
只要是书写代码,都会涉及变量和函数,因此变量和函数命名对于增强代码可读性至关重要。JavaScript 语言的核心 ECMAScript,即是遵照了驼峰式大小写命名法:小写字母开始,后续每个单词首字母都大写。
var thisIsMyName;
var doSomething;
【注意】:驼峰式大小写分为小驼峰式(Camel Case),以及大驼峰式(Pascal Case)。上面所举例子就是小驼峰式,而大驼峰式是首字母大写。
- Google、SproutCore 编程风格指南以及 Dojo 编程风格:推荐使用小驼峰式命名法。
在 2000 年左右,流行另外一种命名方法——匈牙利命名法。名字之前冠以类型标识符前缀,比如 sName 表示字符串,iCounnt 表示整数。不过这种风格已经是明日黄花风光不再,当前主流的编程规范都不推荐这种命名法。
变量和函数
变量名以及函数名都应当总是遵守驼峰大小写命名法。变量名前缀应当是名词,而函数名前缀应当是动词。
// 好的写法
var count = 10;
var myName = "Spirit";
var found = true;
// 不好的写法:变量看起来像函数
var getCount = 10;
var isFount = true;
// 好的写法
function getName() {
return myName;
}
// 不好的写法:函数看起来像变量
function theName() {
return myName;
}
【建议】:
- 命名长度应该尽可能短,并抓住要点;
- 尽量在变量名中体现出值的数据类型;
- 避免使用没有意义的命名。
对于函数和方法命名来说,第一个单词应该是动词,这里有一些使用动词常见的约定。
动词 | 含义 |
---|---|
can | 函数返回一个布尔值 |
has | 函数返回一个布尔值 |
is | 函数返回一个布尔值 |
get | 函数返回一个非布尔值 |
set | 函数用来保存一个值 |
if(isEnabled()) {
setName("Spirit");
}
if(getName() === "Spirit") {
doSomething();
}
尽管这些函数命名细则并没有被归纳入当下流行的编程风格中,但在很多流行的库中,JavaScript 开发者会发现存在不少这种“伪标准”(pseudostandard)。
jQuery 没有遵循这种函数命名约定,一部分在于 jQuery 中方法的使用方式,很多方法同时用作 getter 和 setter。尽管如此,还是推荐使用动词作为函数名前缀。
常量:
在 ECMAScript 6 之前,JavaScript 中并没有真正的常量概念。然而,这并不能阻止开发者将变量用作常量。为了区分普通的变量和常量,一种通用的命名约定应运而生。
// 使用大写字母和下划线来命名,下划线用以分隔单词
var MAX_COUNT = 10;
var URL = "http://www.baidu.com";
构造函数:
在 JavaScript 中,构造函数只不过是前面冠以 new 运算符的函数(在 ES6 之前),用来创建对象。
JavaScript 语言本身已经包含了许多内置构造函数,比如 Object 和 RegExp,同样开发者也可以创建自己的构造函数来生成新类型。
【推荐】:构造函数的命名遵照大驼峰式命名法。
// 好的做法
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
alert(this.name);
};
var me = new Person("spirit");
// 不正确的写法
var me = Person("Spirit");
【说明】:Crockford 编程规范、Google 的 JavaScript 风格指南以及 Dojo 编程风格指南都推荐这种实践。如果构造函数的首字母不是大写的,或者构造函数之前没有 new 运算符,JSLint 都会给出警告。而 JSHint 只有开启 newcap 选项后,才会对首字母不是大写的构造函数给出警告。
直接量(字面量)
JavaScript 中包含一些类型的原始值:字符串、数字、布尔值、null 和 undefined。同样也包含对象直接量和数组直接量。这其中,只有布尔值是自解释(self-explanatory)的,其他的类型或多或少都需要思考一下它们如何才能更精确地表示出来。
字符串:
在 JavaScript 中,字符串是独一无二的。字符串可以用双引号括起来,也可以用单引号括起来。
var name = "Spirit, \"Hello!\"";
var name2 = 'Spirit, "Hello!"';
和 Java、PHP 这些语言不同,使用单引号括起字符串和双引号括起字符串在功能上并无不同。除了内部出现字符串界定符(string delimiter)时需要转义之外,两种做法在功效上完全一致。我们需要关心的是,代码从头到尾保持一种风格。
- Crockford 编程规范:双引号。
- jQuery 核心风格指南:双引号。
- Google:单引号。
【注意】:创建多行字符串时,请使用字符串连接符(+)。
// 非法的 JavaScript 语法,但能在 JS 引擎中正常工作
var longStr = "Here's the story, of a man \
named Spirit.";
// 好的写法
var longStr = "Here's the story, of a man" +
" named Spirit.";
数字:
在 JavaScript 中的数字类型只有一种,因为所有数字形式——整数和浮点数——都存储为相同的数据类型。
有一些数字直接量格式来表示不同的数据格式,其中大部分写法都很好用,但也有一些写法有问题。
// 整数
var count = 10;
// 小数
var price = 10.0;
var price = 10.00;
// 不推荐的写法:没有小数部分
var price = 10.;
// 不推荐的写法:没有整数部分
var price = .1;
// 不推荐的写法:八进制写法已经被弃用了
var num = 010;
// 十六进制写法
var num = 0xA2;
// 科学计数法
var num = 1e23; // 等价于 10 的23次方
小数的写法请尽量不要省略小数以及整数部分。因为这存在一个问题:很难搞清楚是不小心丢掉了还是刻意为之。为了避免歧义,尽量将其书写完整。
长久以来,JavaScript 支持八进制数字写法是很多错误和歧义的根源。数字直接量 010 不是表示 10,而是表示八进制中的 8。大多数开发者对八进制格式并不熟悉,也很少用到,所以最好的做法是在代码中禁止八进制直接量。
null:
null 是一个特殊值,容易将其和 undefined 搞混。我们需要明确在什么场景下使用 null:
- 用来初始化一个变量,这个变量可能赋值为一个对象。
- 用来和一个已经初始化的变量比较,这个变量可以是也可以不是一个对象。
- 当函数的参数期望是对象时,用作参数传入。
- 当函数的返回值期望是对象时,用作返回值传出。
不应当使用 null 的场景:
- 不要使用 null 来检测是否传入了某个参数。
- 不要用 null 来检测一个未初始化的变量。
// 好的用法
var person = null;
function getPerson() {
if(condition) {
return new Person("Spirit");
} else {
return null;
}
}
var person = getPerson();
if(person !== null) {
doSomething();
}
// 不好的用法
var person;
if(person !== null) {
doSomething();
}
function doSomething(arg1, arg2, arg3, arg4) {
if(arg4 != null) {
doSomethingElse();
}
}
理解 null 最好的方式是将它当做对象的占位符。
undefined:
undefined 是一个特殊值。其中一个令人困惑之处在于 null == undefined 的结果是 true。然而,这两个值的用途却各不相同。那些没有被初始化的变量都有一个初始值,即 undefined,表示该变量等待被赋值。
// 不好的写法
var person;
console.log(person === undefined); // true
尽管这段代码能正常工作,但建议还是避免在代码中使用 undefined。因为这个值常常和返回 undefined 的 typeof 运算符混淆。不管是值为 undefined 的变量以及未声明的变量,typeof 运算符返回的结果都为 undefined。
// foo 未被声明
var person;
console.log(typeof person); // undefined
console.log(typeof foo); // undefined
也就是说无法区分值为 undefined 的变量以及未声明的变量。
【问】如何解决这个会产生歧义的问题呢?
【答】通过禁止使用 undefined,可以有效确保只在一种情况下(未声明变量)typeof 返回 undefined。禁止使用 undefined 意味着我们要将未赋值的变量都赋予初值。
对象直接量:
创建对象最流行的一种做法是使用对象直接量,在直接量中直接写出所有属性,这种方式可以取代先显式地创建 Object 的实例然后添加属性的这种做法。
对象直接量允许你将所有的属性都括在一对花括号内。当定义对象直接量时,常常在第一行包含左花括号,每一个属性的键值对都独占一行,并保持一个缩进,最后右花括号也独占一行。
// 不好的写法
var book = new Object();
book.title = "Database";
book.author = "spirit";
// 好的写法
var book = {
title : "Database",
author : "Spirit"
}
尽管没有归纳入文档中,Google 以及 Crockford 编程规范推荐使用这种写法。
数组直接量:
使用两个方括号将数组初始元素括起来,来替代使用 Array 构造函数的方式。
// 不好的写法
var colors = new Array("red", "green", "blue");
var numbers = new Array(1, 2, 3, 4);
// 好的写法
var colors = ["red", "green", "blue"];
var numbers = [1, 2, 3, 4];
Google 以及 Crockford 编程规范推荐这种写法。