Javascript分號(hào)規(guī)則是什么

小編給大家分享一下Javascript分號(hào)規(guī)則是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都做網(wǎng)站、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的文山州網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

分號(hào)允許的場(chǎng)景

分號(hào)一般允許出現(xiàn)在大部分語(yǔ)句(statement)的末尾,比如 do-while statement , var statements, expression statements , continue , return , break statement, throw, debugger 等

栗子:

do Statement while ( Expression ) ;

4+4;

f();

debugger;

僅有一個(gè)分號(hào) ; 可以表示空語(yǔ)句——在JS中合法,比如 ;;; 可解析為三個(gè)空語(yǔ)句(empty statement)

空語(yǔ)句可用于輔助產(chǎn)生語(yǔ)法合法的解析結(jié)果,如:

while(1);

如果沒(méi)有末尾的分號(hào),將會(huì)產(chǎn)生解析錯(cuò)誤 —— 條件循環(huán)后必須跟隨一個(gè)語(yǔ)句

分號(hào)還會(huì)出現(xiàn)在 for 循環(huán) for ( Expression ; Expression ; Expression ) Statement 中

最后,分號(hào)還會(huì)出現(xiàn)在 字符串 或 正則表達(dá)式中 —— 表示分號(hào)本身

分號(hào)可以省略的場(chǎng)景

有些場(chǎng)景下分號(hào)可以省略,解析器在解析語(yǔ)句時(shí)會(huì)根據(jù)需要自動(dòng)插入分號(hào),大概流程可以這樣理解:

書(shū)寫(xiě)省略 => 解析器解析時(shí)發(fā)現(xiàn)缺少時(shí)會(huì)無(wú)法正確解析 => 自動(dòng)添加分號(hào)

so 需要明確能自動(dòng)插入分號(hào)的場(chǎng)景,并明確不會(huì)自動(dòng)插入分號(hào)且會(huì)引起解析錯(cuò)誤的情況

規(guī)則1:當(dāng)下一個(gè) token (offending token) 和當(dāng)前解析的 token (previous token) 無(wú)法組成合法語(yǔ)句,且滿足以下一個(gè)或多個(gè)條件時(shí),將會(huì)在 offending token 前插入一個(gè)分號(hào):

  • offending token 和 previous token 被至少一個(gè)換行符分割(LineTerminator),且分號(hào)插入的作用不是被解析為 空語(yǔ)句 (empty statement)
  • offending token 是 }
  • previous token 是 ), 并且插入的分號(hào)將被解析為do-while語(yǔ)句的終止分號(hào)

還要考慮一種優(yōu)先級(jí)更高的條件:如果插入的分號(hào)會(huì)被解析為一個(gè)空語(yǔ)句,或是 for 語(yǔ)句的頭部?jī)蓚€(gè)分號(hào)之一,這時(shí)不會(huì)插入分號(hào)(除了 do-while 語(yǔ)句的終止分號(hào)外)

規(guī)則2:當(dāng)解析到達(dá)源代碼文件 (input stream) 的末尾時(shí),將自動(dòng)添加一個(gè)分號(hào)標(biāo)識(shí)解析結(jié)束

規(guī)則3:符合 restricted production 語(yǔ)法的語(yǔ)句 —— 比較難翻譯,看不懂的可以直接看栗子,這種情況主要描述的是:不應(yīng)該出現(xiàn)換行符的地方出現(xiàn)換行符導(dǎo)致插入分號(hào)引起原語(yǔ)句含義變化

同時(shí)滿足以下條件,將在 offending token 前自動(dòng)插入一個(gè)分號(hào):

  • offending token 和 previous token 組成合語(yǔ)法的 restricted production 語(yǔ)句
  • offending token 出現(xiàn)于 restricted production 語(yǔ)句描述中的 [no LineTerminaator here] 部分 ( the token would be the first token for a terminal or nonterminal immediately following the annotation “[no LineTerminator here]” within the restricted production )
  • offending token 和 previous token 之間至少存在一個(gè)換行符 (LineTerminator)

其中 restricted production 包括且只有以下:

UpdateExpression[Yield, Await]:
  LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++
  LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] --

ContinueStatement[Yield, Await]:
  continue;
  continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await];

BreakStatement[Yield, Await]:
  break;
  break  [no LineTerminator here]  LabelIdentifier[?Yield, ?Await];

ReturnStatement[Yield, Await]:
  return;
  return  [no LineTerminator here]  Expression  [+In, ?Yield, ?Await];

ThrowStatement[Yield, Await]:
  throw [no LineTerminator here] Expression [+In, ?Yield, ?Await];

ArrowFunction[In, Yield, Await]:
  ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In]

YieldExpression[In, Await]:
  yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await]
  yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await]

簡(jiǎn)單總結(jié):

使用 a++ 語(yǔ)句時(shí),變量和 ++ 必須在同一行,否則會(huì)在 ++ 前插入分號(hào)導(dǎo)致語(yǔ)義不同

return throw yield continue break 后如果緊跟著換行,將會(huì)自動(dòng)添加分號(hào)

箭頭函數(shù)的 => 之前不應(yīng)該有換行符

栗子 & 可能不符合預(yù)期的情況

符合預(yù)期情況

// 相當(dāng)于 42;"hello"
42
"hello"

// offending token 是 }
if(x){y()}

// previous token 是 ) 且插入分號(hào)是 do while 語(yǔ)句的結(jié)束
var a = 1
do {a++} while(a<100)
console.log(a)

//  不會(huì)解析成 b++ 因?yàn)?b和++之間存在換行符,會(huì)在 b 之后自動(dòng)插入分號(hào)
a = b
++c

可能不符合預(yù)期的情況

const hey = 'hey'
const you = 'hey'
const heyYou = hey + ' ' + you

['h', 'e', 'y'].forEach((letter) => console.log(letter))

會(huì)收到錯(cuò)誤 Uncaught TypeError: Cannot read property 'forEach' of undefined , 因?yàn)?you 和 ['h', 'e', 'y'] 的連接能命中合法語(yǔ)法,故它們之間不會(huì)自動(dòng)插入分號(hào) —— 與預(yù)期不一致,JS嘗試將代碼解析為:

const hey = 'hey';
const you = 'hey';
const heyYou = hey + ' ' + you['h', 'e', 'y'].forEach((letter) => console.log(letter))

再看一種情況:

const a = 1
const b = 2
const c = a + b
(a + b).toString()

會(huì)引發(fā) TypeError: b is not a function 報(bào)錯(cuò),因?yàn)闀?huì)被解釋為:

const a = 1
const b = 2
const c = a + b(a + b).toString()

除了 do while 語(yǔ)句外,不會(huì)有插入分號(hào)作為空語(yǔ)句的其他情況,或作為 for 語(yǔ)句頭部的兩個(gè)必要分號(hào) :

if (a > b)
else c = d

for (a; b
)

以上均不是合法的 JS 語(yǔ)句,并且會(huì)引起報(bào)錯(cuò)

故以下栗子中的每一個(gè)分號(hào)都不能省略??!

// for循環(huán)沒(méi)有循環(huán)體的情況,每一個(gè)分號(hào)都不能省略
for (node=getNode();
     node.parent;
     node=node.parent) ;

再看一個(gè)帶詳細(xì)注釋的例子:

var         // 這一行不會(huì)插入分號(hào) ,因?yàn)?下一行的代碼不會(huì)破壞當(dāng)前行的代碼  
    a = 1   // 這一行會(huì)插入分號(hào)   
let b = 2   

// 再比如這種情況,你的原意可能是定義 `a` 變量,再執(zhí)行 `(a + 3).toString()`,
// 但是其實(shí) JavaScript 解析器解析成了,`var a = 2(a + 3).toString()`,
// 這時(shí)會(huì)拋出錯(cuò)誤 Uncaught TypeError: 2 is not a function
var a = 2
(a + 3).toString()

// 同理,下面的代碼會(huì)被解釋為 `a = b(function(){...})()`
a = b
(function(){
...
})()

以上都是未能命中規(guī)則1而未插入分號(hào)導(dǎo)致解析與預(yù)期不符合的情況

看一個(gè)基于規(guī)則3的例子:

(() => {
  return
  {
    color: 'white'
  }
})()

預(yù)期是返回一個(gè)包含 color 屬性的對(duì)象,但事實(shí)上 return 后會(huì)被插入一個(gè)分號(hào),而導(dǎo)致最終返回 undefined,可以通過(guò)在 return 后立刻放置花括號(hào) { :

(() => {
  return {
    color: 'white'
  }
})()

省略分號(hào)的最佳實(shí)踐

不要使用以下單個(gè)字符 ( [ / + - 開(kāi)始一行 , 會(huì)極有可能和上一行語(yǔ)句合在一起被解析( ++ 和 -- 不符合單個(gè) +、- 字符)

注意 return break throw continue 語(yǔ)句,如果需要跟隨參數(shù)或表達(dá)式,把它添加到和這些語(yǔ)句同一行,針對(duì) return 返回內(nèi)容較多的情況 (大對(duì)象,柯里化調(diào)用,多行字符串等),可以參考規(guī)則1,避免命中該規(guī)則而引起非預(yù)期的分號(hào)插入,比如:

return obj.method('abc')
          .method('xyz')
          .method('pqr')
 
return "a long string\n"
     + "continued across\n"
     + "several lines"
 
totalArea = rect_a.height * rect_a.width
          + rect_b.height * rect_b.width
          + circ.radius * circ.radius * Math.PI

后綴運(yùn)算符 ++ -- 需要和操作變量在同一行使用

當(dāng)然大部分工程化情況下,我們最終會(huì)配合Eslint使用帶分號(hào)或省略分號(hào)規(guī)范

以上是“Javascript分號(hào)規(guī)則是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

文章題目:Javascript分號(hào)規(guī)則是什么
文章源于:http://muchs.cn/article0/ghscio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、面包屑導(dǎo)航、用戶體驗(yàn)、企業(yè)建站、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站