99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋(píng)果6袋
6
麥子學(xué)院

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

發(fā)布時(shí)間:2016-10-30 19:40  回復(fù):0  查看:3313   最后回復(fù):2016-10-30 19:40  

之前的朋友寫(xiě)信來(lái)問(wèn),因?yàn)樵谧x到我個(gè)人寫(xiě)的一本電子書(shū),我在寫(xiě)作風(fēng)格里有說(shuō)明,這本電子書(shū)中javascript語(yǔ)言的范例都是使用"不用分號(hào)(;)作為代碼語(yǔ)句的結(jié)尾"的風(fēng)格。

  所以我把所有的回答整出出來(lái)這篇文章,并針對(duì)常見(jiàn)的問(wèn)題回答。

  前言

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

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

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

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

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

  //有問(wèn)題的例子function add() {

  var a = 1, b = 2;

  return

  a + b;

  }

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

  //有問(wèn)題的例子function test() {

  return

  {

  test: true

  };

  }

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

  function test() {

  return;

  { test: true };

  }

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

  那為何回車(\\n)或換行,可以作為語(yǔ)句的結(jié)尾?來(lái)源是由于ECMAScript的自動(dòng)插入分號(hào)(Automatic Semicolon Insertion, 以下簡(jiǎn)稱ASI)的標(biāo)準(zhǔn)。在語(yǔ)句或一段代碼敘述后,加了回車(\\n)后,JS剖析器會(huì)在執(zhí)行期間自動(dòng)幫你插入分號(hào),這樣理解了嗎?所以不是回車(\\n)的事,是因?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開(kāi)發(fā)者,這是很基礎(chǔ)的一些知識(shí)。

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

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

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

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

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

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

  //第一例var a =

  [ 1,2,3,

  ]

  //第二例function test(a,

  b,

  c){console.log(a,b,c

  )

  }

  2. 這一行是++--

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

  a=1--

  a

  console.log(a)

  3. 這一行是for()、while()do、if()else,但沒(méi)有用花括號(hào)({})時(shí)

  這簡(jiǎn)寫(xiě)語(yǔ)法也很常見(jiàn),每天都會(huì)用到,是個(gè)當(dāng)執(zhí)行代碼不多時(shí)的寫(xiě)法。以下為范例:

  if(null==undefined)

  console.log(true)else

  console.log(false)

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

  以下為范例:

  function test(){

  return 1

  +2

  -3

  }console.log(test())

  下面這個(gè)例子剛好與第一點(diǎn)顛倒的寫(xiě)法,也很常見(jiàn),有人喜歡用這種的寫(xiě)法,有些人喜歡用第一點(diǎn)的:

  var a =

  [1

  ,2

  ,]

  5: 空白語(yǔ)句不會(huì)自動(dòng)結(jié)尾

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

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

  if (i === 5)

  else console.log(false)

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

  //合法例子var i = 10

  if (i === 5);

  else console.log(false)

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

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

  一個(gè)小常識(shí)是,分號(hào)(;)除了作為語(yǔ)句結(jié)尾或分隔外,它與JS中的其他符號(hào)有個(gè)差異,它自己本身可以形成一個(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è)表述式彼此之間:

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

  for(var i=0 ; i<10 ; i++)

  {

  //...

  }

  2. 在同一行寫(xiě)兩個(gè)語(yǔ)句(表述式)在一起,中間需要分號(hào)(;)區(qū)隔。

  所以像 switch 語(yǔ)句中的 case ,如果 break (或 continue )要寫(xiě)在同一行時(shí), break (或 continue )前必加分號(hào)(;),以下為例子:

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

  //第二例case 'foo': doSomething(); break

  3. 以 或 開(kāi)頭的行,前面需要加分號(hào)(;)

  這是很特別一種撰寫(xiě)風(fēng)格。實(shí)際上是一種保護(hù)防范的語(yǔ)法,有時(shí)候解譯器或壓縮工具會(huì)誤認(rèn)為某行語(yǔ)句,有開(kāi)頭 ( 的話是準(zhǔn)備要作函數(shù)呼叫,或開(kāi)頭 [ 是準(zhǔn)備要作數(shù)組(陣列)或?qū)ο?/span>(物件)的存取屬性的事。

  還有另一情況是IIFE,因?yàn)?/span>IIFE剛好也是用 ( 開(kāi)頭。所以這兩種開(kāi)頭的語(yǔ)句前,必加分號(hào)(;)在語(yǔ)句的最前面,以免造成誤判。不過(guò)大概也只有這一個(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)來(lái)作每行語(yǔ)句的結(jié)尾,你應(yīng)該了解一下。

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

  畫(huà)蛇添足不多說(shuō),一定會(huì)造成錯(cuò)誤,其實(shí)這錯(cuò)誤很難犯,只是網(wǎng)上有我把它列出來(lái)。

  //錯(cuò)誤語(yǔ)法for (var i=0; i < 10; i++;){}

  2. 花括號(hào)的結(jié)尾(})的后面。但有例外,賦值時(shí)可以加分號(hào)(;)是對(duì)的語(yǔ)法。

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

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

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

  //正確語(yǔ)法,do...whiledo {...} while (...);

  3. iffor、while、或switch的圓括號(hào)結(jié)尾后面加上分號(hào)(;)

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

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

  //上例相當(dāng)于下面這樣if (0 === 1);alert("hi");

  反對(duì)的原因,以及說(shuō)明

  以下針對(duì)幾個(gè)常見(jiàn)的反對(duì)不使用分號(hào)作為語(yǔ)句結(jié)尾的理由,以我的所知回答這些原因。不過(guò),大部份都是因?yàn)?/span>FUD(懼、惑、疑),而不是真正以理解或科學(xué)實(shí)證的角度。

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

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

  自動(dòng)插入分號(hào)其實(shí)是本來(lái)就有的語(yǔ)言特性,網(wǎng)上可以找到的2000年的ECMAScript版本3,也就是ES3標(biāo)準(zhǔn),里面就有這個(gè) Automatic Semicolon Insertion 章節(jié)了。

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

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

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

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

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

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

  最近的在JSMinBootstrap中的一段代碼爭(zhēng)議在這里可以看到,JS發(fā)明人Brendan Eich的言論立場(chǎng)是會(huì)中立些https://brendaneich.com/2012/...

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

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

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

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

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

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

  結(jié)語(yǔ)

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

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

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

 

文章來(lái)源:SegmentFault

您還未登錄,請(qǐng)先登錄

熱門(mén)帖子

最新帖子

?