编程风格 - 第 4 章 变量、函数、运算符
《编写可维护的 JavaScript》—— Nicholas C. Zakas
JavaScript 编程的本质是编写一个个函数来完成任务。
在函数内部,变量和运算符可以通过移动、操作字节来使某件事发生。
关注如何使用函数、变量、运算符来减少复杂度和增强可读性就显得十分重要。
1. 变量声明
用 var
声明的变量会提前到函数顶部。
变量声明提前意味着:在函数内部任意地方定义变量和在函数顶部定义变量是完全一样的。
建议将所有的局部变量的定义作为函数内第一条语句。
2. 函数声明
函数声明也会提前。
推荐先声明函数再使用。
此外,函数声明不应当出现在语句块之内,如下
if (true) {
function doSomething() {
alert('Hi!');
}
} else {
function doSomething() {
alert('Hello!');
}
}
大多数浏览器会使用第二个声明,Firefox 会根据条件判断使用第一个声明。
3. 函数调用间隔
一般情况下,对于函数调用写法推荐的风格是:在函数名和左括号之间没有空格。
这样做是为了将它和块语句区分开来。
// 好的写法
doSomething(item);
// 不好的写法
doSomething (item);
// 块语句
while (item) {
// ...
}
4. 立即调用的函数
JavaScript 中允许声明匿名函数(没有命名的函数),并将匿名函数赋值给变量或属性。
var doSomething = function() {
// ...
}
这种匿名函数可以在最后加一对圆括号来立即执行并返回一个值,然后将这个返回值赋值给变量。
// 不好的写法
var value = function() {
return 100;
}();
这种模式的问题在于会让人误以为将一个匿名函数赋值了这个变量。
除非看到最后一行的那对圆括号,否则你不会知道是将函数赋值给变量,还是将函数的执行结果赋值给变量。
这种困惑会影响代码的可读性。
为了一眼就能看出是立即执行的函数,可以将它用一对圆括号整个包起来。
// 好的写法
var value = (function() {
return 100;
}());
5. 严格模式
ES5 引入了严格模式(strict mode),希望通过这种方式来谨慎地解析执行 JavaScript,以减少错误。
'use strict';
尽管看起来像一个没有赋值给变量的字符串,但 ES5 JavaScript 引擎会将其识别为一条指令,以严格模式来解析代码。
这条编译指令(pragma)不仅用于全局,也适用于局部(如函数内)。
不建议将 use strict
用在全局作用域,这会让文件中的所有代码都以严格模式来解析。
如果将 10 个文件合并为一个文件时,当其中一个文件在全局作用域使用了 use strict
,则所有代码都将以严格模式解析。
由于严格模式中的运算规则和非严格模式下的情形有很大不同,
因此其他文件中的(非严格模式下)代码很可能会报错。
6. 相等
由于 JavaScript 具有强制类型转换机制,使用 ==
或 !=
会产生意料之外的结果,如下
5 == '5'; // true
1 == true; // true
0 == false; // true
null == undefined; // true
推荐使用 ===
或 !==
6.1. eval()
eval()
可以将传入的字符串当做代码来执行,
使用 Function
构造函数、setTimeout()
、setInterval()
也可以将字符串当做代码来执行。
一个通用的原则是,
严禁使用 Function
,只有在万不得已的情况下使用 eval()
,往 setTimeout()
里传入函数而非字符串。
6.2. 原始包装类型
JavaScript 有 3 种原始包装类型:String
、Boolean
、Number
。
var name = 'Nicholas';
console.log(name.toUpperCase());
name
是一个字符串,是原始类型而不是对象,但可以使用 toUpperCase()
之类的方法,即将字符串当做对象来对待。
这行代码的背后 JavaScript 引擎创建了 String
类型的新实例,调用完方法后就销毁掉了。
推荐避免使用包装类型。
开发者的思路常常会在对象和原始值之间跳来跳去,这样会增加 bug 的概率,从而使开发者陷入困惑。