这一章,我们主要关注如何使用函数、变量和运算符来减少复杂度和增强可读性。
4.1 变量声明
让我们来看一个例子
function add(){
var result = 10 + value;
var value = 10;
return result;
}
add() ==> NaN
这段代码中,变量value提前参与了result的计算
以上的代码被JS理解为如下代码(因为js的变量提升)
function add(){
var result;
var value;
result = 10 + value;
value = 10;
return result;
}
再来看看一段代码。
function doSomething(items){
for(var i = 0, len = items.length; i < len; i++){
add(items[i])
}
}
在ECMAScript5之前,JS没有块级变量声明,这段代码实际上等价于:
function doSomething(items){
var i, len;
for(i = 0, len = items.length; i < len; i++){
add(items[i])
}
}
变量声明提前意味着:在函数内部任意地方定义变量和在函数顶部定义变量是完全一样的。
所以,可以将所有变量声明放在函数顶部,而不是散落在各个角落。
推荐写法:将局部变量的定义作为函数内第一条语句,在顶部使用单var语句,没有初始值的变量,应当出现在var语句尾部。
function doSomething(items){
var value = 10,
result = value + 10,
i,
len;
for(i = 0, len = items.length; i < len; i++){
add(items[i])
}
}
4.2 函数声明
和变量声明一样,函数声明也会被JS引擎提前。因此,在代码中函数的调用可以出现在函数声明之前。
//不好的写法
doSomething();
function doSomething() {
alert('hello world')
}
这段代码可以正常运行,因为JS引擎将这段代码解析为:
function doSomething() {
alert('hello world')
}
doSomething();
此外,函数声明不应当出现在语句块之内。比如,这段代码:
var container = true;
if( container ){
function doSome(){
alert('HI')
}
doSome();
} else {
function doSome(){
alert('Yo')
}
doSome();
}
亲测,这种情况下,由于两个函数名都叫doSome,
在IE10及以下浏览器,不管container值为什么,都会执行 alert('Yo')
这种场景是ECMAScript的一个灰色地带,应当尽可能避免。
4.3 函数调用间隔
4.4 立即调用的函数
看看以下代码:
var value = function() {
return {
message: 'HI'
}
}();
这段代码的问题是:会让人误以为将一个匿名函数赋值给了这个变量。除非读完代码看到最后一行那对圆括号,否则你不会知道是将函数赋值给变量还是将函数的执行结果赋值给变量。
这种困惑会影响代码的可读性。
//推荐写法
var value = (function(){
//函数体
return {
message: 'HI'
}
}());
这段代码在第一行就有了一个标识符(左圆括号),表明这是一个立即执行的函数。
4.5 严格模式
"user strict"
不推荐将"user strict" 用在全局作用域中,尽量使局部严格模式、
//推荐写法
(function(){
"user strict"
function doSomething() {
//代码
}
function doSomethingElse() {
//代码
}
})();
4.6 相等
如果一个布尔值和数字比较,布尔值会首先转换为数字,然后进行比较。
false值变为0,true变为1.
1 == true ==> true
0 == true ==> true
2 == true ==> false
如果一个值是对象而另一个不是,则会首先调用对象的valueOf()方法,得到原始类型值再进行比较。如果没有定义valueOf(),
则调用toString()。
null == undefined ==> true
4.6.1 eval()
在JS中,eval()不是唯一可以执行JS字符串的函数,使用Function构造函数,setTimeout()和setInterval()也可以。
var myfunc = new Function("alert('HI')")
不过,使用以上三种方法来直接执行字符串代码,被认为是一种糟糕的实践。
一个通用的原则是,严禁使用Function,并且只在别无他法时使用eval(),setTimeout()和setInterval()也可以使用,但不要用字符串,而要用函数形式。
setTimeout(function(){
//代码
}, 50)