セミコロンに぀いお知っおおくべきこず

セミコロン ";"の自動挿入は、javascriptの最も物議を醞す機胜の1぀であり、その呚蟺には倚くの誀解が蓄積されおいたす。



䞀郚のプログラマヌは「;」を入れたす 各ステヌトメントの最埌に、䞀郚は厳密に必芁な堎合のみ。 䜙分な「;」を远加するものもありたすが、ほずんどは䞭間のどこかにありたす 文䜓的な理由から。



垞に「;」を入れおも 各ステヌトメントの最埌に、いく぀かの構文が自明な方法で解析されたす。 「;」に関する奜みに関係なく、蚀語を専門的に䜿甚するには、そのような解析の芏則を知っおおく必芁がありたす。 以䞋のいく぀かの簡単なルヌルを思い出しお、プログラムがどのように解析されるかを理解し、自動挿入「;」の゚キスパヌトになりたす。 JavaScriptで。







TKが蚱容される堎合





ECMAscript仕様で指定されおいる正匏な文法では、「;」 各挔算子の末尟にありたす。 do-whileステヌトメントは次のずおりです。



doステヌトメントwhile匏;



TKは、varステヌトメント、匏ステヌトメント「4 + 4;」たたは「f;」など、continue、return、break、throwステヌトメントおよびデバッガヌステヌトメントの最埌の文法にも衚瀺されたす。



空のステヌトメントは「;」であり、javascriptの正しいステヌトメントです。 このため、「;;;」 有効なプログラムであり、3぀の空のステヌトメントずしお解析され、3回は実行されたせん。



少なくずも構文的には、空のステヌトメントが圹立぀堎合がありたす。 たずえば、無限ルヌプの堎合、「while1;」ず蚘述できたす。セミコロンは空のステヌトメントずしお解析され、whileステヌトメントが構文的に有効になりたす。 TKがないず、ルヌプ条件の埌に挔算子が必芁になるため、whileステヌトメントは䞍完党になりたす。



最埌に、「;」 ルヌプでは「forExpression; Expression; ExpressionOperator」の圢匏で䜿甚されたす。もちろん、小文字および正芏衚珟リテラルで䜿甚できたす。



セミコロンをスキップできる堎所





ECMAscript仕様の正匏な文法では、「;」 䞊蚘のずおり。 ただし、この仕様では、実際の構文解析が正匏な文法ずどのように異なるかを蚘述する芏則も提䟛しおいたす。 ルヌルは、入力ストリヌムに挿入された想像䞊の「;」で蚘述されたすが、これは単なる仕様モデルです。実際には、パヌサヌは擬䌌「;」を生成する必芁はありたせんが、「;」 特定の堎所でのオプションの文法ずしおたずえば、ECMAscriptの構文解析、特にStatement、EOS、EOSnoLB、およびSnoLBルヌルを参照。 仕様で「挿入」、「」ず曞かれおいる箇所は、珟圚のステヌトメントが終了するこずを意味したす。



TKの自動挿入のルヌルは、 ECMA-262 [pdf]のセクション7.9で説明されおいたす。



このセクションでは、3぀のルヌルず2぀の䟋倖を瀺したす。



ルヌルは次のずおりです。



プログラムが文法䞊無効なトヌクンに遭遇するず、aこの堎所に改行がある堎合、たたはb無効なトヌクンが閉じ䞭括匧の堎合、「;」が挿入されたす。 ファむルの終わりに到達し、異なる解釈が䞍可胜になるず、「;」が挿入されたす。 文法で「[ここにLineTerminatorがありたせん」」ず曞かれおいる堎所に行末蚘号を含む「制限されたプロダクション」が衚瀺されたら、「;」が挿入されたす。



蚀い換えれば、これらの芏則は、挔算子が「;」なしで終了できるず蚀っおいたす。 a右䞭括匧の前、bプログラムの最埌、c次のトヌクンを解析できない堎合、さらに、改行がステヌトメントを無条件に完了するいく぀かの堎所がありたす。 これが実際に䜕を意味するかを以䞋で説明したす。



䟋倖「;」 「forExpression; Expression; ExpressionOperator」および「;」ずいう圢匏のルヌプヘッダヌに挿入されない 結果が空のステヌトメントの堎合は挿入されたせん。



これはすべお私たちにずっお䜕を意味したすか



たず、「;」 行末、䞭括匧の前、およびプログラムの最埌でのみオプションです。 さらに、「;」 次の行の最初のトヌクンが前のステヌトメントの䞀郚ずしお解析できる堎合、行末で想定されおいたせん。



「42; "hello" "は有効なプログラムの䟋であり、" 42 \ n "hello" "where" \ n "改行を衚すが、" 42 "hello" "は行の折り返しが自動挿入を匕き起こすため、もはや存圚しない。 「スペヌスはありたせん。 「Ifx{y}」も有効です。 ここで、「y」は「;」で終わるこずができる匏ステヌトメントですが、次のトヌクンは右䞭括匧なので、「;」 オプション、改行なしにもかかわらず。



forルヌプず空のステヌトメントの䞡方の䟋倖を䞀緒に説明できたす。



  fornode = getNode;
      node.parent;
      node = node.parent; 




ルヌプは、芪のないノヌドが芋぀かるたで次の芪ノヌドを順番に呌び出したす。 これはすべおルヌプヘッダヌで行われるため、ルヌプ本䜓には䜕も残りたせん。 ただし、ルヌプ構文には挔算子が必芁であり、空の挔算子を挿入したす。 3぀すべおが「;」であるずいう事実にもかかわらず この䟋では、行末に「;」があるため、3぀すべおが必芁です。 ルヌプヘッダヌに挿入されないか、空のステヌトメントを䜜成したせん。



限定スポヌン





限定されたスポヌンでは、特定の堎所で改行を芋぀けるこずができたせん。これらの堎所で改行するず、プログラムは同じ方法で解析されたせんが、異なる方法で解析できるためです。



文法には5぀の制限されたスパンがありたす。これらは、埌眮挔算子++および-、continue、break、およびreturnステヌトメントです。 breakおよびcontinueステヌトメントには、特定のルヌプから制埡を枡すためのオプションの識別子が含たれる堎合がありたす。 この機胜を䜿甚する堎合、識別子は同じ行になければなりたせん。 これは有効なプログラムです。

 var c、i、l、quitchars
 quitchars = ['q'、 'Q']
 charloopwhilec = getc{
     fori = 0; i <quitchars.length; i ++{
         ifc == quitchars [i]break charloop
     }
     / * ...他の文字のコヌド... * /
 }




getcが入力ストリヌムから文字を返す堎合、プログラムはそれを読み取り、出力文字かどうかを確認し、出力文字である堎合は、ルヌプの制埡を枡したす。 マヌクされたbreakステヌトメントは、内偎のルヌプだけでなく、倖偎のルヌプから抜け出すために必芁です。 改行のみが異なる同じプログラムでは、同じ結果は埗られたせん。

 var c、i、l、quitchars
 quitchars = ['q'、 'Q']
 charloopwhilec = getc{
     fori = 0; i <quitchars.length; i ++{
         ifc == quitchars [i]break
            チャヌルヌプ
     }
     / * ...他の文字のコヌド... * /
 }




この堎合、charloopトヌクンはbreakステヌトメントの䞀郚ではありたせん。 breakステヌトメントは制限されおいるため、この䜍眮での改行によりステヌトメントが完了したす。 charloopトヌクンはcharloop倉数のように解析されたすが、この堎所は制埡されず、breakステヌトメントは意図したずおりに倖郚ルヌプではなく内郚ルヌプを終了したす。



他の4぀の境界付きスポヌンの䟋



 // PostfixExpression                                            
 // LeftHandSideExpression [LineTerminatorはありたせん] ++
 // LeftHandSideExpression [ここにLineTerminatorはありたせん]-
 var i = 1;
私は
 ++;




これにより゚ラヌがスロヌされ、「i ++」ずしお解析されたせん。 タヌミネヌタは、埌眮むンクリメントたたはデクリメント挔算子を分離できないため、行の先頭の「++」たたは「-」は前の行の䞀郚ずしお解析されるこずはありたせん。



私は
 ++
 j




これは間違いではなく、「i;」ずしお解析されたす。 ++ j。 " プレフィックスのむンクリメントずデクリメントは限定的な䞖代ではないため、「++」たたは「-」ずそれらが倉曎する匏の間で改行が発生する堎合がありたす。



 // ReturnStatementreturn [LineTerminator here here] Expressionopt;
åž°ã‚‹
   {ii、jj}




これは、空のreturnステヌトメントずしお解析され、その埌に制埡が到達しない匏挔算子が続きたす。 ただし、蚈画どおりに解析されたす。



 return {
   ii、jj}
リタヌン
   {ii、jj}
 return {ii
        、jj}




returnステヌトメントには匏の䞭にハむフンが含たれおいる堎合がありたすが、returnトヌクンず匏の先頭の間にはない堎合がありたす。 「;」を意図的に省略した堎合、returnステヌトメントの限定生成は䟿利です。これは、次の行から誀っお匏を返すこずなく空のreturnを曞き蟌むこずができるためです。



関数初期化a{
   // aがすでに初期化されおいる堎合、戻りたす
   ifa.initializedreturn
   a.initialized = true
   / * ... ...を初期化したす* /
 }




continueおよびthrowステヌトメントは、breakおよびreturnに䌌おいたす。



 innerloopを続行// true
 
続ける
     innerloop;  //間違っおいる
 // ThrowStatementthrow [no LineTerminator here] Expression;
 throw //解析゚ラヌ
   new MyComplexErrora、b、c、more、args;
 // return、break、continueずは異なり、 
 //スロヌ埌の匏が必芁です、 
 //したがっお、䞊蚘はたったく解析されたせん。
新しいMyComplexErrora、b、c、more、argsをスロヌしたす。  // true
新しいMyComplexError
     a、b、c、more、args;  //たた真
 // throwずnewが同じ行にあるオプションはすべお正しいです。




むンデントはECMAscriptプログラムの解析には関係なく、改行の有無が再生されたす。 したがっお、javascriptの゜ヌスコヌドプロセッサは、プログラムのセマンティクスに圱響を䞎えるこずなく、先頭のスペヌス文字列定数を陀くをカットできたすが、改行を任意にカットしたり、スペヌスやセミコロンに眮き換えるこずはできたせん。 有効なプログラムのセマンティクスを倉曎するミニファむダは、䟡倀のない無効なミニファむダであり、唯䞀の方法は完党で正しいパヌサヌを蚘述するこずです。



return、break、continue、および++および-の前の改行は、解析に圱響したす。 これらの補品のみが制限されおいるため、プログラムの読みやすさを改善するために、スペヌスず改行を他のどこでも自由に䜿甚できたす。 特に、論理、算術、文字列連結挔算子、トリプルたたは条件付き挔算子、ピリオドたたはブラケットを介したメンバヌぞのアクセス、関数呌び出し、forルヌプ、switchステヌトメント、およびその他の制埡構造は、どこでも改行を䜿甚しお蚘述できたす。



仕様は次のずおりです。



ECMAScriptプログラマ向けの実甚的なアドバむス埌眮挔算子「++」ず「-」は、オペランドず同じ行にある必芁がありたす。 returnたたはthrowステヌトメントの匏は、returnたたはthrowトヌクンず同じ行で開始する必芁がありたす。 breakたたはcontinueステヌトメントの識別子は、breakたたはcontinueトヌクンず同じ行になければなりたせん。




スポヌンが制限されおいるプログラマの最も䞀般的な間違いは、特にラヌゞオブゞェクトたたは配列リテラルが返される堎合、たたは耇数行定数の堎合、戻りトヌクンの埌に行に戻り倀を配眮するこずです。 このような改行がほずんどのプログラマヌにずっお䞍自然であるず思われるずいう事実のため、埌眮挔算子、およびbreak、continue、throw挔算子の゚ラヌは実際にはたれです。



自動挿入「;」の最埌の埮劙さ 最初のルヌルに埓い、「;」を挿入するための無効なトヌクンをプログラムに含める必芁がありたす。 オプションの「;」をスキップする堎合は、スキップできないオプションではないものがあるこずに泚意しおください。 このルヌルを䜿甚するず、ステヌトメントを耇数行にわたっおストレッチできたす。



 return obj.method 'abc'
           .method 'xyz'
           .method 'pqr'
 
 「長い文字列\ n」を返したす
      +「ストレッチ\ n」
      +「耇数の堎合」
 
 totalArea = rect_a.height * rect_a.width
           + rect_b.height * rect_b.width
           + circ.radius * circ.radius * Math.PI




ルヌルは、文字列の最初のトヌクンにのみ適甚されたす。 このトヌクンを挔算子の䞀郚ずしお解析できる堎合、挔算子は続行したす解析がさらに倱敗しおも。 オペレヌタヌが最初のトヌクンを続行できない堎合、次のトヌクンが開始されたすこの時点で、仕様には「挿入」、「」ず衚瀺されたす。



ペアの挔算子AずBの䞡方が個別に有効な堎合に゚ラヌが発生する可胜性がありたすが、最初のトヌクンBはAの継続ずしおも受け入れられたす。そのような堎合、「;」がない堎合、パヌサヌはBを個別の挔算子ずしお解析したせん。゚ラヌ、たたは予期しない方法でプログラムを解析したす。 したがっお、「;」 スキップされた堎合、プログラマは改行で区切られた挔算子AずBを監芖する必芁があり、BはAの末尟に付加できるトヌクンで開始したす。



JavaScriptのほずんどの挔算子は識別子で始たり、残りのほずんどは「var」、「function」、「if」などのキヌワヌドで始たりたす。 識別子たたはキヌワヌドで始たるこのような挔算子B、および文字列定数で始たる行には、有効な挔算子Aは存圚したせん蚀語の文法からのこの蚌明は、読者の緎習ずしお残されおいたす。



 A
関数fx{return x * x}
 
 // TKのない挔算子Aの堎合
 //これらの䟋はすべお正しく解析されたす
 
 A
 f7
 
 A
 「文字列」.length




残念ながら、オペレヌタヌを開始し、既に完了したトヌクンを継続できる5぀のトヌクンがありたす。 これらは「」、「[」、「/」、「+」、「-」です。実際には、最初の2぀が問題を匕き起こしたす。



これは、垞に改行が「;」を眮き換えるこずができるずは限らないこずを意味したす。 オペレヌタヌ間。



仕様には䟋を瀺したす。

                    a = b + c
                    d + e.print


かっこ内の匏は関数呌び出しの匕数ずしお解析できるため、自動挿入「;」では倉換できたせん。

                    a = b + cd + e.print


仕様では、「代入挔算子が巊角かっこで始たる必芁がある堎合、前の行に明瀺的にセミコロンを配眮するこずをお勧めしたす。」 より厳密な代替策は、TKを行の先頭、トヌクンの盎前に蚭定するこずです。これにより、あいたいさが生じるリスクがありたす。

                    a = b + c
                    ;d + e.print


括匧たたは角括匧で始たる挔算子はたれですが、発生したす。



map、filter、forEachなどの「機胜的な」操䜜は配列でより頻繁に行われるため、角括匧を䜿甚した䟋はより頻繁に行われたす。 倚くの堎合、副䜜甚に必芁なforEachを含む倧芏暡なリテラルを䜜成するず䟿利です。

 [['January'、 'Jan']]
 、['February'、 'Feb']
 、[「3月」、「3月」]
 、['April'、 'Apr']
 、[「5月」、「5月」]
 、['June'、 'Jun']
 、[「7月」、「7月」]
 、[「8月」、「8月」]
 、[「9月」、「9月」]
 、['October'、 'Oct']
 、[「11月」、「11月」]
 、[「12月」、「12月」]
 ] .forEach関数a{print "略語" + a [0] + "is" + a [1] + "。"}
 
 ['/script.js'
 、 '/ style1.css'
 、「/ style2.css」
 、「/ page1.html」
 ] .forEach関数uri{
   ログ「ルックアップずキャッシュ」+ uri
    fetch_and_cacheuri}


代入で倧芏暡なリテラルが䜿甚される堎合、たたは関数が枡される堎合、ステヌトメントの先頭には衚瀺されないため、最初の開き角括匧はたれですが、発生したす。



最埌の問題トヌクンはスラッシュであり、非垞に盎感的ではありたせん。 芋おみたしょう

 var i、s
 s = "here is a string"
 i = 0
 /[az.BIZ/g.exec(s


1行目から3行目で倉数を開始し、4行目でrex参照リテラル "/ [az] / g"を䜜成したす。これはazをグロヌバルに怜玢し、execメ゜ッドを䜿甚しおこの正芏衚珟を文字列で呌び出したす。 execの戻り倀は䜿甚されないため、コヌドは特に有甚ではありたせんが、少なくずもコンパむルされるこずが期埅されたす。 ただし、スラッシュは正芏衚珟を開始するだけでなく、陀算挔算子でもありたす。 ぀たり、行4の先頭のスラッシュは、前の行の代入挔算子の継続ずしお解析されたす。 これらの行は、「iは0に等しい[az]による陀算はg.execsによる陀算に等しい」ず解析されたす。



実際には、正芏衚珟挔算子を開始する理由はほずんどないため、この問題はほずんど発生したせん。 䞊蚘の䟋では、execの呌び出しの倀は通垞、関数に枡されるか、倉数に割り圓おられたす。いずれの堎合も、行はスラッシュで始たりたせん。 ここでも、䟋倖ずしおforEachメ゜ッドがありたす。これは、execを呌び出しお返される倀に察しお[ original䟿利に䜿甚 ]を䟿利に䜿甚できたす。



挔算子「+」および「-」を単項ずしお䜿甚しお、倀を数倀型に倉換し、「-」の堎合に笊号を逆にするこずができたす。 行の先頭で「;」を䜿甚した堎合 それらは、察応する2項挔算子、および前の挔算子の継続ずしお認識できたす。 しかし、これはめったに問題になりたせん。最初の単項挔算子はregexpよりも䞀般的ではないからですたた、完党に芋えたせん。 正芏衚珟ず同様に、プログラマヌが倀を数倀にキャストしたい堎合、䜕らかの方法でこの倀を䜿甚し、倉数に割り圓お、たたは関数に枡したすが、単項挔算子は先頭にありたせん。

 var x、y、z
 x = + y;  //䟿利
 y = -y;  //䟿利
印刷-y;  //䟿利
 + z;  //圹に立たない


そのような堎合はすべお、「;」を省略するず、セミコロンのようにブラケットで行を開始するのが安党な方法です。 挔算子「+」、「-」、たたはスラッシュのたれなケヌスに぀いおも同じアドバむス。 したがっお、TKがどこでも䜿甚されおいない堎合でも、前の行がどのように倉化するかに関係なく、行は誀った解析から保護されたす。



誀解





倚くの初心者のJavascriptプログラマヌは、「;」 すべおの堎所で、自動挿入ルヌル「;」を䜿甚しない堎合、蚀語のこのプロパティは無芖できるず考えおいたす。 䞊蚘の制限された生成ルヌル、特にreturnステヌトメントのため、これは圓おはたりたせん。 そしお、圌らは限られた産卵に慣れるず、改行を恐れ始め、読みやすさを改善したずしおも避けたす。 自動挿入「;」のルヌルを孊習しお、任意のコヌドを読み取り、最も明確な方法でコヌドを蚘述できるようにするこずをお勧めしたす。



もう1぀の誀解は、javascriptブラりザ゚ンゞンのバグにより、どこでもセミコロンの信頌性が高くなり、互換性が向䞊するずいうこずです。 これは単にそうではありたせん。 すべおの既存のブラりザは、自動挿入「;」に関しお仕様を正しく実装しおおり、存圚する可胜性のあるバグは、Webの初期の歎史の闇に長く入り蟌んでいたす。 ブラりザの互換性を心配する理由はありたせん。すべおのブラりザは䞊蚘のルヌルを実装しおいたす。



おわりに





セミコロンを入れるべきですか あなたのビゞネス。 単玔に、遞択は情報に基づいお行われるべきであり、未知の構文トラップや存圚しないブラりザのバグに察する挠然ずした恐怖ではありたせん。 これらのルヌルを芚えおいれば、正しい遞択の準備ができおいるので、javascriptのコヌドを簡単に読むこずができたす。



「;」を付けないこずにした堎合、それらを開始する挔算子、および「/」、「+」、「-」で始たる挔算子では、そのような挔算子を蚘述した堎合は、開き角括匧の前に眮くこずをお勧めしたす。



セミコロンに関係なく、制限された生成の芏則戻り、ブレヌク、継続、スロヌ、および埌眮むンクリメントおよびデクリメント挔算子を芚えおおいおください。コヌドの利䟿性ず読みやすさのために、他の堎所で行を分割できたす。



All Articles