|
|
|
|
|
在JavaScript編程中,按照編程習(xí)慣,你可能會(huì)在每個(gè)句末加上一個(gè)分號(hào)(;
),但是我們又發(fā)現(xiàn),現(xiàn)在很多程序根本就不再使用分號(hào)了,句末直接為空(什么符號(hào)都不寫),并且也不影響程序的正常運(yùn)行。所以JavaScript加不加分號(hào)似乎沒有什么不同。不過(guò)如果深入研究,JavaScript加不加分號(hào)并不完全相同,在某些情況下,是必須添加分號(hào)的。
至于加不加分號(hào)關(guān)鍵點(diǎn)則需要了解分號(hào)對(duì)于JavaScript 的影響。
立即函數(shù)與分號(hào)的關(guān)系
下面程序的運(yùn)行預(yù)期為:
a
的值為1請(qǐng)問(wèn)這段程序運(yùn)行是否正確?
var a = 1
(function() {
console.log(2)
})()
.
.
.
.
如果你嘗試運(yùn)行這段程序,則會(huì)出現(xiàn)此錯(cuò)誤:
Uncaught TypeError: 1 is not a function
什么?1 is not a function?我們沒有打算運(yùn)行數(shù)字1,為何要說(shuō)數(shù)字1 不是函數(shù),這種錯(cuò)誤很難查找到原因,常常會(huì)在錯(cuò)誤的行數(shù)上打轉(zhuǎn)。這個(gè)錯(cuò)誤主要原因是上述程序運(yùn)行時(shí)被視為同一行,概念如下:
var a = 1(function() { /* */ })()
因此立即函式的 ()
附加在1 上,這是一個(gè)調(diào)用函數(shù)的語(yǔ)法,所以會(huì)造成 1 is not a function 的錯(cuò)誤,如果要避免此錯(cuò)誤就需要使用分號(hào)將其隔開:
var a = 1; // 用分號(hào)隔開就對(duì)了
(function() {
console.log(2)
})()
return 與分號(hào)的關(guān)系
再來(lái)看一個(gè)片段,以下程序中在return
的后方空一行后再回傳值,請(qǐng)問(wèn)運(yùn)行結(jié)果是什么呢?
function fn() {
return
'小明'
}
console.log(fn())
這段程序在 return
后方會(huì)被加上一個(gè)分號(hào),也因?yàn)槿绱耍?code>return 與預(yù)期回傳的值被分了開來(lái),所以return
的內(nèi)容為空值,最終函數(shù)也僅能接收到 undefined
的結(jié)果。
function fn() {
return;
'小明';
}
console.log(fn()); // undefined
所以,分號(hào)到底要怎么處理呢?
ASI「Automatic Semicolon Insertion」自動(dòng)插入分號(hào), 是修正沒有加入分號(hào)的片段代碼,但偏偏有些地方?jīng)]有發(fā)揮其用途(如本篇一開始所介紹到的立即函數(shù)),導(dǎo)致程序出現(xiàn)了錯(cuò)誤;甚至有些程序不會(huì)出錯(cuò),但會(huì)讓你的程序運(yùn)行結(jié)果不如預(yù)期。
要解決ASI 的問(wèn)題,解決方式如下:
不會(huì)自動(dòng)加入分號(hào)的規(guī)則
以下整理各種「不會(huì)」自動(dòng)加入分號(hào)的規(guī)則:
1、新的一行是(
、[
、/
開始,這類型通常會(huì)直接出現(xiàn)「Uncaught TypeError」導(dǎo)致程序無(wú)法運(yùn)行(其后方的程序也會(huì)無(wú)法運(yùn)作)。
var a = 1
var b = a
(a + b).toString()
var a = 1
[1,2,3].forEach(bar)
(function() { })()
(function() { })()
var a = 1
var b = a
/test/.test(b)
2、新的一行以 +
、-
、*
、%
作開始,這類型大多數(shù)會(huì)影響運(yùn)算結(jié)果,建議合并為一行寫。
var a = 2
var b = a
+a
3、新的一行以,
、.
作開始,這類型在實(shí)戰(zhàn)中很常會(huì)運(yùn)用,主要是避免程序代碼過(guò)長(zhǎng)所加入的分段,并不會(huì)影響運(yùn)行,多加善用可使程序代碼更易于閱讀。
var a = 2
var b = a
.toString()
console.log(typeof b)
var a = 1
,b = 2 // b 一樣會(huì)被 var 聲明
因此,遇到以上的標(biāo)點(diǎn)符號(hào)前方加入分號(hào)也是解決辦法。
如果需要加入分號(hào)的狀況,除了在語(yǔ)句的末端加入分號(hào)外,也可將分號(hào)改在「不會(huì)自動(dòng)加入分號(hào)」的最前方,如 ()
本身不會(huì)自動(dòng)加入分號(hào),當(dāng)有此需求時(shí)可以將 ;
加入至前方以避免錯(cuò)誤。
// 執(zhí)行錯(cuò)誤
(function() { })()
(function() { })()
// 正確
;(function() { })()
;(function() { })()
結(jié)論
不加入分號(hào)可以讓程序看起來(lái)更干凈、精簡(jiǎn)(對(duì)于習(xí)慣加入分號(hào)的開發(fā)者可能并不這樣認(rèn)為),且在大部分正確的分段下并不會(huì)出現(xiàn)錯(cuò)誤,僅有少部分的語(yǔ)句會(huì)出現(xiàn)執(zhí)行上的錯(cuò)誤(很少,大多都可避免),因此許多開發(fā)者也會(huì)選擇不加入分號(hào)。
而加入分號(hào)會(huì)讓人覺得代碼分段分明,可讀性更強(qiáng),所以很多人喜歡這樣的寫代碼習(xí)慣。
至于選擇何種,只要清楚運(yùn)行上的限制,其實(shí)并無(wú)什么不同。