一行過長的代碼會影響閱讀體驗. 實際項目中,咱們每每把過長的代碼分紅多行去寫.
好比在js中, promise鏈常常要分紅多行寫. 對此本人想到一個問題, 就是js中, 在什麼地方換行是合法而且不破壞原有代碼邏輯的.html
探究這個問題過程當中本人造了一個小玩具, breakline, 顧名思義, 它的做用就是在不破話代碼的邏輯的狀況下把js代碼拆成多行. 項目地址:https://github.com/flowmemo/b...git
咱們接下來仍是談換行的問題. 爲了簡單起見, 本文不討論註釋中的換行符.github
在通常的語言中, 換行符通常是意味着一個statement1的結束, 分號也一般有這個做用. 可是js中換行符並無表明statement的結束的意思. 事實上在規範中, 換行符(規範中稱爲line terminator)在多數狀況下和空格、tab的做用是同樣的, 是爲了分隔token以及方便閱讀, 除了...express
換行符在某些狀況下會觸發自動分號插入(Automatic Semicolon Insertioin, 如下簡稱ASI)promise
換行符自己是token的一部分, 好比在StringLiteral(單/雙引號字符串, 必須經過`來escape), Template和TemplateSubstitutionTail(這兩個就是*
*包起來的字符串)中.工具
如下爲ECMA-262 7.0(也就是ES七、ES2016)規範中相應的描述:rest
A line terminator cannot occur within any token except a StringLiteral, Template, or TemplateSubstitutionTail. Line terminators may only occur within a StringLiteral token as part of a LineContinuation.code
有了這些信息, 咱們就應該知道在什麼狀況下能夠換行了:只要你的新加的換行符不在上述的兩個規則內就行.htm
咱們再繼續探究這兩個規則.token
EMCA規範中有一部分專門講了ASI, 在http://www.ecma-international...
對於ASI這裏就不展開細講了, 這裏只說ASI和換行相關的部分.
一個狀況是, 換行符後的token和以前的token一塊兒進行parse會出錯, 那麼換行符後的token叫作offend token. Offend token前會自動插入一個分號.
舉例:
var foo foo = 2
一共5個token, 按前後順序是var
, foo
, foo
, =
, 2
. parser先解析了前兩個token, 很好, 沒錯, 而後接着parse下一個token foo
, 出錯了(由於沒有一個js語法中並無一條production包含var foo foo
的形式). 因而ASI被觸發, 在換行符和offend token間加了個分號. var foo
就被parse成了Variable Statement, 而後後面的foo = 2
也被成功parse了2.
Restricted production規定了觸發ASI的幾種特殊狀況.
如下幾個位置出現換行符, 即便以後的token能夠繼續被合法parse, 也會觸發ASI
後綴自增/自減運算符以前
continue, break, return, throw, yield以後
arrow function的=>
以前
因此咱們要比儘可能避免在上述位置加換行符(除非你知道本身是在作什麼).
這部分簡而言之就是不要在表示字符串內容的部分換行. 這個很好理解了.
須要注意的是對於有替換的部分, 也就是${}
的花括號內部,是能夠看成普通的expression換行的
也就是說
var s = `hello ${person.name}!`
var s = `hello ${ person . name }!`
是相同的.
在探究這個過程當中本人寫了breakline. 這個工具的目的就是把你的js代碼拆成多行, 同時又不對代碼的功能和邏輯形成實質的影響.
在實際寫代碼過程當中, 符合普通人邏輯的「正常」的換行是沒有問題的. 若是說有須要注意的地方,也就是restricted production的第二條了, continue, break, return, throw, yield這幾個關鍵字以及=>
後不要換行, 其餘的地方換行的話...能夠說也沒什麼美感了, 通常人不會那麼幹的.
注
[1] 關於statement和expression的區別, 能夠參考http://www.2ality.com/2012/09...
[2] 實際上在foo = 2
後也自動插入了一個分號.