亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript里的語(yǔ)句用分號(hào)結(jié)尾是個(gè)選項(xiàng)嗎

stormzhang / 3235人閱讀

摘要:在以下的種情況是用回車或換行,是不會(huì)作自動(dòng)插入分號(hào)來讓語(yǔ)句作結(jié)尾。以下情況必用分號(hào)。但有例外,賦值時(shí)可以加分號(hào)是對(duì)的語(yǔ)法。

起因

這個(gè)文章一開始回覆于這篇回答中: javascript初級(jí)問題

也有之前的朋友寫信來問,因?yàn)樵谧x到我個(gè)人寫的一本電子書: 從ES6開始的JavaScript學(xué)習(xí)生活,繁體,gitbook。我在寫作風(fēng)格里有說明,這本電子書中的范例都是使用"不用分號(hào)(;)作為代碼語(yǔ)句的結(jié)尾"的風(fēng)格。

所以我把所有的內(nèi)容整理出來到這篇文章,并針對(duì)一些常見的反對(duì)問題作解說回答。

覺得寫得好的朋友請(qǐng)分享給你的朋友,或點(diǎn)個(gè)推薦。這些知識(shí)是很基本的,但可惜一直被忽視。

前言

先說明我并沒有要大家都來不加分號(hào),而是回答"為什么可以不加分號(hào)",或是"為何分號(hào)是選項(xiàng)可有可無?",或是"分號(hào)是在何時(shí)可以不加?何時(shí)又一定要加?何時(shí)又算多加了?"等問題。

"不用分號(hào)作語(yǔ)句結(jié)尾"并不是"完全不使用分號(hào)",而是該加的時(shí)候加,不該加的時(shí)候不加,不用分號(hào)作為語(yǔ)句結(jié)尾。實(shí)際上,我如果在改寫別人的代碼或是像原本函式庫(kù)(如jquery)的風(fēng)格是有用分號(hào)(;)時(shí),為了統(tǒng)一撰寫風(fēng)格,也是會(huì)加的,基本上自己最近寫的ES6、React、Redux等就不用分號(hào)(;)結(jié)尾。

分號(hào)(;)的作用

在JS里的分號(hào)(;)是什么作用?總結(jié)一下,它既是語(yǔ)句(表達(dá)式)的分隔,也可以作為語(yǔ)句的結(jié)尾。

但只認(rèn)為分號(hào)(;)就一定是語(yǔ)句的結(jié)尾是有疑問的,下面這兩個(gè)例子就是典型范例,也是很常見的錯(cuò)誤:

//有問題的例子
function add() {
  var a = 1, b = 2;
  return
    a + b;
}

或是像下面這個(gè),也是很常見的錯(cuò)誤示范:

//有問題的例子
function test() {
  return
    {
      test: true
    };
}

這兩例的函數(shù)回傳值必為undefined,而不是應(yīng)該回傳的值3與物件。為何?因?yàn)槟阌锌吹絩eturn先換行(回車),再接著要回傳的值了嗎?也就是說這兩個(gè)代碼在執(zhí)行時(shí),相當(dāng)于下面這樣的代碼(我只寫一個(gè)出來,另一例相同):

function test() {
  return;
  { test: true };
}

return因?yàn)橄葥Q了一行,視為語(yǔ)句結(jié)尾,所以根本沒有可回傳的值,也就是在上例子中,回車( )先把return結(jié)尾掉了,后面你加的分號(hào)(;)是結(jié)尾到下一行的。這邏輯代表回車( )在這一句語(yǔ)句結(jié)尾這功用上,比分號(hào)(;)還優(yōu)先。

那為何回車( )或換行,可以作為語(yǔ)句的結(jié)尾?來源是由于ECMAScript的自動(dòng)插入分號(hào)(Automatic Semicolon Insertion, 以下簡(jiǎn)稱ASI)的標(biāo)準(zhǔn)。在語(yǔ)句或一段代碼敘述后,加了回車( )后,JS剖析器會(huì)在執(zhí)行期間自動(dòng)幫你插入分號(hào),這樣理解了嗎?所以不是回車( )的事,是因?yàn)樽詣?dòng)幫你加分號(hào)作結(jié)尾了。

自動(dòng)插入分號(hào)(ASI)這個(gè)規(guī)則一直在網(wǎng)上有爭(zhēng)議,有一群人認(rèn)為它是個(gè)容易造成誤解的設(shè)計(jì),有一群人認(rèn)為它這設(shè)計(jì)是正確的,應(yīng)該多多利用,就像不需要在一般情況下再多此一舉,在語(yǔ)句后面加上分號(hào)(;)。不管你是支援哪一種,我認(rèn)為都需要理解其中的內(nèi)容,作為一個(gè)稱職的JS開發(fā)者,這是很基礎(chǔ)的一些知識(shí)。

自動(dòng)插入分號(hào)(ASI)的5種例外情況

這里討論的就是用回車( )或斷行來作為語(yǔ)句的結(jié)尾,自動(dòng)插入分號(hào)(Automatic Semicolon Insertion)標(biāo)準(zhǔn)的特例情況。在以下的5種情況是用回車( )或換行,是不會(huì)作自動(dòng)插入分號(hào)來讓語(yǔ)句作結(jié)尾。雖是說"例外情況",但大概也是每天都看得到,只是常不知道為何會(huì)這樣而已,看了你就知道了。大致說明如下:

1. 當(dāng)這一行的語(yǔ)句是沒關(guān)閉的情況

例如數(shù)組(陣列)、對(duì)象(物件)文字字面、圓括號(hào)之類,或是最后是個(gè)點(diǎn)號(hào)(.)或逗號(hào)(,)時(shí),也就是如果把這行結(jié)尾,就會(huì)產(chǎn)生不合法語(yǔ)句的情況。

注: 遇到等號(hào)(=)算未完整的表述式,如果指定值在下一行也會(huì)略過自動(dòng)插入分號(hào)結(jié)尾作用

這種例子很常見,通常是在分開內(nèi)容太長(zhǎng)的語(yǔ)句,或是讓值寫得清楚的地方。我舉下面的兩個(gè)合法語(yǔ)法范例,你會(huì)很容易理解回車( )會(huì)在何時(shí)自動(dòng)結(jié)尾,雖然這些例子是不好閱讀的例子,一般情況我們會(huì)用來分隔比較長(zhǎng)的語(yǔ)句:

//第一例
var a =
[ 1,
2,
3,
] 

//第二例
function test(a,
b,
c){
console.log(a,b,c
)
}
2. 這一行是++或--

這規(guī)則是很怪異的,從來沒看過有人這樣寫過。JS會(huì)認(rèn)為++與--在這一行是要準(zhǔn)備來運(yùn)算執(zhí)行下一行的值,所以不結(jié)尾。下面是個(gè)合法范例:

a=1
--
a
console.log(a)
3. 這一行是for()、while()、do、if()或else,但沒有用花括號(hào)({})時(shí)

這簡(jiǎn)寫語(yǔ)法也很常見,每天都會(huì)用到,是個(gè)當(dāng)花括號(hào)({})區(qū)塊中執(zhí)行代碼不多時(shí)用的語(yǔ)法。以下為范例:

if(null==undefined)
   console.log(true)
else
   console.log(false)
4. 下一行的開頭是([)、(()、(+)、(*)、(/)、(-)、(,)、(.),或二進(jìn)位運(yùn)算子(例如~ & |),可以與這行組成一個(gè)表達(dá)式時(shí)

以下為范例:

function test(){
  return 1
         +2
         -3
}
console.log(test())        

下面這個(gè)例子剛好與第一點(diǎn)顛倒的寫法,也很常見,也是一個(gè)用于長(zhǎng)語(yǔ)句的寫法。有人喜歡用這種的寫法,有些人喜歡用第一點(diǎn)的寫法:

var a = 
[1
,2
,] 
5: 空白語(yǔ)句,不會(huì)自動(dòng)插入分號(hào)作結(jié)尾

這與上面第3點(diǎn)有相關(guān),有時(shí)候會(huì)看到有人犯了這個(gè)常見錯(cuò)誤。下面是個(gè)錯(cuò)誤例子,不論if這行與else這行間有沒有換行,或是換了幾百行,都不會(huì)自動(dòng)插入分號(hào)作結(jié)尾:

//錯(cuò)誤例子
var i = 10

if (i === 5)

else  console.log(false)

不過,你可以加上分號(hào)在if(...)這行最后,讓語(yǔ)法合法可被執(zhí)行。但真心沒見過有人這樣用,控制流程邏輯不對(duì)才會(huì)這樣寫。下面為合法例子:

//合法例子
var i = 10

if (i === 5);

else  console.log(false)

以上為用回車(n)作為語(yǔ)句結(jié)尾的的5個(gè)例外情況,其他都會(huì)自動(dòng)幫你插入分號(hào)作結(jié)尾。

所以依這個(gè)解說,最一開始的例子中的return后面多了一個(gè)換行就會(huì)產(chǎn)生錯(cuò)誤的回傳值。與return有同樣情況的還有幾個(gè),像continue、breakthrow等四個(gè)關(guān)鍵字,這些如果先換行,然后在下一行再加分號(hào)也是會(huì)變成兩個(gè)不同的語(yǔ)句,因?yàn)樵趽Q行時(shí)已經(jīng)自動(dòng)插入分號(hào)結(jié)尾掉。

一個(gè)小常識(shí)是,分號(hào)(;)除了作為語(yǔ)句結(jié)尾或分隔外,它與JS中的其他符號(hào)有差異,是它自己本身可以形成一個(gè)合法的語(yǔ)句(表達(dá)式)。你可以在程式碼里只輸入一個(gè)分號(hào)(;),它是合法而不會(huì)報(bào)錯(cuò)的,其他的符號(hào)(例如:,:+-*/%)都會(huì)報(bào)錯(cuò)。

一定要使用分號(hào)的情況

分號(hào)(;)的用處不是只有語(yǔ)句結(jié)尾,它在某些語(yǔ)法中,具有分隔表述式或語(yǔ)句的功用。以下情況必用分號(hào)(;)。

1. for語(yǔ)句圓括號(hào)(())中的三個(gè)表述式彼此之間:

很常用到,不多加說明了,以下為例子:

for(var i=0 ; i<10 ; i++)
{
 //... 
}
2. 在同一行寫兩個(gè)語(yǔ)句(表述式)在一起,中間需要分號(hào)(;)區(qū)隔。

所以像switch語(yǔ)句中的case,如果break(或continue)要寫在同一行時(shí),break(或continue)前必加分號(hào)(;)。這在語(yǔ)句很短的時(shí)很會(huì)用到。以下為例子:

//第一例
var i = 0; i++ 

//第二例
case "foo": doSomething(); break
3. 以[(開頭的行,前面需要加分號(hào)(;)

這是很特別一種撰寫風(fēng)格。實(shí)際上是一種保護(hù)防范的語(yǔ)法,有時(shí)候解譯器或壓縮工具會(huì)誤認(rèn)為某行語(yǔ)句,有開頭(的話是準(zhǔn)備要作函數(shù)呼叫,或開頭[是準(zhǔn)備要作數(shù)組(陣列)或?qū)ο?物件)的存取屬性的事。所以會(huì)與上幾行粘在一起剖析,造成代碼執(zhí)行結(jié)果不對(duì)或報(bào)錯(cuò)。

還有另一情況是IIFE,因?yàn)镮IFE剛好也是用(開頭。所以這兩種開頭的語(yǔ)句前,必加分號(hào)(;)在語(yǔ)句的最前面,以免造成誤判。不過大概也只有這一個(gè)需要特別注意,IIFE你用到的情況有可能會(huì)多些。以下為例子:

//第一例
;(x || y).doSomething()
;[a, b, c].forEach(doSomething)

//第二例
var x = 42
;(function () { })()

參考: http://stackoverflow.com/ques...

"不需要"與"一定不能"使用分號(hào)的情況

接著要理解,什么時(shí)候必"不需要"與"一定不能"使用分號(hào)(;),這也很容易理解的。如果你是都要用分號(hào)來作每行語(yǔ)句的結(jié)尾,你應(yīng)該了解一下。

1. for語(yǔ)句的最后一個(gè)(第三個(gè))表達(dá)式后面

畫蛇添足不多說,一定會(huì)造成錯(cuò)誤,其實(shí)這錯(cuò)誤很難犯,只是網(wǎng)上其他文章有列,所以我把它也列出來。

//錯(cuò)誤語(yǔ)法
for (var i = 0; i < 10; i++;){}
2. 花括號(hào)的結(jié)尾符號(hào)(})的后面。但有例外,賦值時(shí)可以加分號(hào)(;)是對(duì)的語(yǔ)法。

這個(gè)規(guī)則理論上應(yīng)該是"不需要"加而已,經(jīng)測(cè)試在Chrome上也不會(huì)報(bào)錯(cuò),算是不建議的語(yǔ)法,這也是個(gè)畫蛇添足。

//不建議語(yǔ)法
function a(){};
if(){};

//正確語(yǔ)法,賦值時(shí)使用
var obj = {a:1};
var fun = function(){};

//正確語(yǔ)法,do...while
do {...} while (...);
3. 在if、for、while、或switch的圓括號(hào)結(jié)尾符號(hào)())后面加上分號(hào)(;)

這個(gè)是合法語(yǔ)法,但整個(gè)控制邏輯是錯(cuò)掉的,這錯(cuò)誤很也不容易犯到。可以對(duì)照到最上面一節(jié)的第5個(gè)例外情況看看。

//錯(cuò)誤例子,不過它合法
if (0 === 1); { alert("hi") }

//上例相當(dāng)于下面這樣
if (0 === 1);
alert("hi");
反對(duì)的原因,以及說明

以下列出幾個(gè)常見的反對(duì)"不使用分號(hào)作為語(yǔ)句結(jié)尾"的原因,以這些原因的解說。不過這些原因,大部份都是因?yàn)镕UD(懼、惑、疑),而不是真正以理解或科學(xué)實(shí)證的角度。

因?yàn)闉g覽器相容問題。舊版的瀏覽器不支持。

自動(dòng)插入分號(hào)(ASI)的標(biāo)準(zhǔn)是何時(shí)加到ECMAScript的?

自動(dòng)插入分號(hào)其實(shí)是本來就有的語(yǔ)言特性,網(wǎng)上可以找到的2000年的ECMAScript版本3,也就是ES3標(biāo)準(zhǔn),裡面就有這個(gè)Automatic Semicolon Insertion章節(jié)了。2000年到現(xiàn)在也十多年了,你說要多舊的瀏覽器才真的不支持,說真的我也找不到。

根據(jù)網(wǎng)上的文章指出,曾經(jīng)有一小段時(shí)間IE6這個(gè)在ASI實(shí)作上有問題,但后來MS很快修正了,現(xiàn)在我們能用到的IE6是支持的。下圖是在WindowsXP SP3中的IE6瀏覽器中的小小測(cè)試,你可以仔細(xì)看一下,執(zhí)行的代碼并沒有用分號(hào)來作語(yǔ)句結(jié)尾,而且是直接寫在HTML文檔中。

所以,你是聽誰(shuí)說舊版的瀏覽器不支援的?該不會(huì)那個(gè)人又說他也是聽說的。謠言止于智者對(duì)吧。

因?yàn)閴嚎s工具不支持

這原因以前的確存在過,有個(gè)壓縮工具叫JSMin,是大師Douglas Crockford寫的工具,如果你沒用分號(hào)作語(yǔ)句結(jié)尾,它是連壓都不壓。當(dāng)然這是因?yàn)镃rockford他本來就不太贊成不用分號(hào)作語(yǔ)句結(jié)尾的關(guān)系。

現(xiàn)在老早就沒有這問題了,其他常用的工具如Closure Compiler或webpack中的壓縮外掛工具都可以壓好壓滿,要不然怎么會(huì)有知名的一些大專案(bootstrap, npm, vue.js)也舍棄用分號(hào)作語(yǔ)句結(jié)尾的情況。

最近的在JSMin與Bootstrap中的一段代碼爭(zhēng)議在這里可以看到,JS發(fā)明人Brendan Eich的言論立場(chǎng)是會(huì)中立些,你有興趣可以進(jìn)一步看這篇: https://brendaneich.com/2012/...

語(yǔ)句都用分號(hào)(;)作結(jié)尾是一個(gè)好的撰寫風(fēng)格

最有名的是從JSLint這個(gè)檢查工具開始的,它會(huì)檢查你的每個(gè)語(yǔ)句的最后是不是用分號(hào)(;)來作結(jié)尾,如果不是會(huì)提出警告信息。

而提倡在每個(gè)語(yǔ)句后面一定要用分號(hào)來作結(jié)尾的大師級(jí)人物,最有名的算是JSON格式發(fā)明者Douglas Crockford,他的這個(gè)文章上有說明,從文章中可以看得出他是反對(duì)只使用ASI特性的。JSLint工具也是他作的,相信也有很多人看過他的大作"JavaScript: 優(yōu)良部份"。不過,他也提倡了很多風(fēng)格,例如tab鍵相當(dāng)于4個(gè)空格,但現(xiàn)在一般都用2個(gè)空格,或是一行一個(gè)var變量定義,而且要按照英文字母排列,不知道有多少人真的是一定這樣作。大師耳提面命的東西,我們小小程序員當(dāng)然必定是要重視,但并不是照單全收。

回到我們的問題中,在瀏覽器上能順利執(zhí)行的代碼語(yǔ)法,為何要檢查工具要強(qiáng)迫認(rèn)為是有問題的語(yǔ)法?

如果你都到處都加上分號(hào)(;),卻還會(huì)發(fā)生有錯(cuò)誤的情況(例如最上面的典型例子),那代表起因是來自于對(duì)于語(yǔ)言本身的無知,而不能怪罪于語(yǔ)言本身的臭蟲或設(shè)計(jì)問題。

現(xiàn)在流行的其他檢查工具,例如ESLint、JSHint等等,就算有這項(xiàng)檢查也有選項(xiàng)可以關(guān)閉。這純粹是開發(fā)團(tuán)隊(duì)或個(gè)人的選擇才是正確的。

結(jié)語(yǔ)

要不要用分號(hào)(;)作為語(yǔ)句的結(jié)尾,就視個(gè)人習(xí)慣或組織團(tuán)隊(duì)規(guī)定的撰寫風(fēng)格了。不管你的選擇為何,都應(yīng)該理解為何分號(hào)(;)是選項(xiàng)而非必要的原因,不要因?yàn)榇笊窕蛏缛荷洗蠹艺f要加該加,就埋頭拼命加,而不去理解其中的原因。

真實(shí)情況是并不是所有的情況分號(hào)作為語(yǔ)句都是選項(xiàng),是有規(guī)則標(biāo)準(zhǔn)的。js雖然常常有坑,但本質(zhì)上是死的東西,標(biāo)準(zhǔn)就已經(jīng)定在那里了,上面我所說的規(guī)則學(xué)好足以應(yīng)付9成情況,也可以讓你的代碼寫起來更加有信心。

說句實(shí)在話,如果你是個(gè)能把加分號(hào)(;)的行為減到最少情況,也就是不使用分號(hào)作為語(yǔ)句的結(jié)尾的程序員,是因?yàn)槟憷斫夥痔?hào)(;)在JS中的意義,以及ASI標(biāo)準(zhǔn)的規(guī)則。并不是標(biāo)新立異或追求潮流,也不是為了要少打那幾個(gè)符號(hào),更不是為了要讓js檔壓縮后會(huì)變小,這純粹是個(gè)笑話,完全不會(huì)變小,因?yàn)閴嚎s工具實(shí)際上會(huì)幫你加上分號(hào)。

最后幾句,開源專案中真的完全不使用分號(hào)(;)的專案最近多起來的現(xiàn)象,但最有名的是大家每天都在用的npm、bootstrap,還有最近比較火紅的vue.js、redux這幾個(gè),有興趣可以找找。

參考

http://blog.izs.me/post/23534...

http://mislav.net/2010/05/sem...

http://inimino.org/~inimino/b...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/91099.html

相關(guān)文章

  • JavaScript ASI 機(jī)制詳解

    摘要:最近在清理的未讀列表,看到了才知道了的,一種自動(dòng)插入分號(hào)的機(jī)制。這種行為被叫做自動(dòng)插入分號(hào),簡(jiǎn)稱。不過在省略分號(hào)的風(fēng)格中,這種解析特性會(huì)導(dǎo)致一些意外情況。規(guī)則標(biāo)準(zhǔn)定義的包括三條規(guī)則和兩條例外。規(guī)則一情況三就是為量身定做的。 TL;DR 最近在清理 Pocket 的未讀列表,看到了 An Open Letter to JavaScript Leaders Regarding Semico...

    frontoldman 評(píng)論0 收藏0
  • 備胎的自我修養(yǎng)——趣談 JavaScript 中的 ASI (Automatic Semicolon

    摘要:行結(jié)束符之后的符號(hào)有二義性,使得該符號(hào)與上條語(yǔ)句能夠無縫對(duì)接,不導(dǎo)致語(yǔ)法錯(cuò)誤。然而在中,有幾種特殊語(yǔ)句是不允許行結(jié)束符存在的。如果語(yǔ)句中有行結(jié)束符,會(huì)優(yōu)先認(rèn)為行結(jié)束符表示的是語(yǔ)句的結(jié)束,這在標(biāo)準(zhǔn)中稱為限制產(chǎn)生式。 showImg(https://segmentfault.com/img/bVmyZB); 什么是 ASI ? 自動(dòng)分號(hào)插入 (automatic semicolon i...

    _ipo 評(píng)論0 收藏0
  • php-cs-fixer - PHP 編碼格式化工具

    摘要:是個(gè)代碼格式化工具,格式化的標(biāo)準(zhǔn)是以及一些的標(biāo)準(zhǔn)。這個(gè)工具也和等優(yōu)秀的庫(kù)出自同門。如果同時(shí)設(shè)定了和,前者的優(yōu)先級(jí)更高。同時(shí)使用和命令可以顯示出需要修改的匯總,但是并不實(shí)際修改。你可以設(shè)置格式化的選項(xiàng)級(jí)別文件以及目錄。 php-cs-fixer 是個(gè)代碼格式化工具,格式化的標(biāo)準(zhǔn)是 PSR-1、PSR-2 以及一些 symfony 的標(biāo)準(zhǔn)。這個(gè)工具也和 symfony、twig 等優(yōu)秀的 ...

    ityouknow 評(píng)論0 收藏0
  • JavaScript 編寫規(guī)范

    摘要:如果你想了解更多關(guān)于強(qiáng)制類型轉(zhuǎn)換的信息,你可以讀一讀的這篇文章。在只使用的情況下,所帶來的強(qiáng)制類型轉(zhuǎn)換使得判斷結(jié)果跟蹤變得復(fù)雜,下面的例子可以看出這樣的結(jié)果有多怪了明智地使用真假判斷當(dāng)我們?cè)谝粋€(gè)條件語(yǔ)句中使用變量或表達(dá)式時(shí),會(huì)做真假判斷。 說明 如果本文檔中有任何錯(cuò)誤的、不符合行規(guī)的,敬請(qǐng)斧正。 引言 不管有多少人共同參與同一項(xiàng)目,一定要確保每一行代碼都像是同一個(gè)人編寫的。...

    MartinDai 評(píng)論0 收藏0
  • JavaScript 函數(shù)的定義

    摘要:關(guān)鍵詞必須是小寫的,并且必須以與函數(shù)名稱相同的大小寫來調(diào)用函數(shù)。當(dāng)調(diào)用函數(shù)時(shí),這些標(biāo)識(shí)符則指代傳入函數(shù)的實(shí)參。函數(shù)表達(dá)式其實(shí)是忽略函數(shù)名稱的,并且不可以使用函數(shù)名這種形式調(diào)用函數(shù)。注意構(gòu)造函數(shù)無法指定函數(shù)名稱,它創(chuàng)建的是一個(gè)匿名函數(shù)。 一、關(guān)于函數(shù) JavaScript函數(shù)是指一個(gè)特定代碼塊,可能包含多條語(yǔ)句,可以通過名字來供其他語(yǔ)句調(diào)用以執(zhí)行函數(shù)包含的代碼語(yǔ)句。 比如我們有一個(gè)特定的...

    mudiyouyou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<