grammatical-rule

JavaScriptの文法規則 文、式、演算子

前回は、5つの基本型とオブジェクト型 JavaScriptの型についてまとめた。ここでは、JavaScriptの文法規則 文、式、演算子について解説する。

1 式と文の構造

JavaScriptのソースコードは文の集まりである。文は文と式から構成される。式は式と演算子から構成される。 式を最後まで分解すると、識別子(変数名や関数名)とリテラル値(数値や文字列の直接表記)と演算子(記号が予約語)になる。

 

2 予約語

予約語(reserved word)はECMAScript第5版は以下の5つに分解される。

  • キーワード:break、do、instanceofなど
  • 将来の予約語:class、enum、extendsなど
  • null:リテラル値
  • true:リテラル値
  • false:リテラル値

 

3 識別子

識別子は変数名や関数名など、開発者がプログラムの中で定義する単語である。識別子の規則は以下の4つである。

  • 予約語以外の単語
  • true、false、null以外の単語
  • Unicodeの(非空白)文字で始まり、その後にUnicodeの文字または数字が続く単語
  • 単語の長さの制限は特にない

 

4 リテラル表記

リテラル(literal)表記とは、コード上に書いた値が実行時にその値のまま意味を持つ仕組みのことである。例えば「var foo = “bar”;」というコードの場合、varは変数宣言を意味する言語規則でそれ自体は意味を持たない。同時にfooとして割り当てられた領域を示すだけである。一方、barという単語は実行時にbarという文字の並びとしての意味を持つ。”bar”は文字列値のリテラル表記である。また、例えば「var val0 = 0;」の場合、val0は変数名の一部として0であり、右辺のリテラル表記の0は数値としての意味を持つ。

 

5 文とは

プログラミング言語における(statement)は、その言語の文法で明確に定義された構文(syntax)規則で決まる。文はプログラムの実行時に実行(execute)される。つまり、文を次々に実行していくことをプログラムの実行と呼ぶこともできる。なお、JavaScriptの文はセミコロンで区切る。

 

6 ブロック文(複合文)

ブロック文は中カッコ({})の間に文を並べた文である。複数の文の集まりを文として扱える。JavaScriptのブロックでの留意点は、変数にブロックスコープがない点である。

 

7 変数宣言文

変数宣言文はキーワードvar、次に変数名を続ける。変数名をカンマ(,)で区切ると複数並べられる。=演算子を使うと宣言と同時に初期化ができる。

 

8 関数宣言文

返り値の型の代わりにキーワードfunctionで始めることと引数に型指定がないことを除けば、Javaのメソッド定義とほぼ同じ構文である。関数名と引数には識別子を書く。引数は任意個数並べられる。

 

9 式文

式文とは式がそのまま文になる文法規則である。JavaScriptではすべての式が式文にできる。Javaは無意味な式文をコンパイルエラーで弾くが、JavaScriptはエラーにはならない。

 

10 空文

空文とはセミコロンが1つだけの文である。空文を書かなくても、意味的にも文法的にも問題はない。

 

11 制御文

制御文により逐次処理(上から下)以外の処理の流れが発生する。条件分岐、繰り返し、ジャンプ(例外処理を含む)の3つに分類できる。

 

12 if-else文

ifに対応する条件式と文を合わせてif節、elseに対応する条件式と文を合わせてelse節と呼ぶ。if文はelse節を省略したif-else文と見ることも可能である。条件式と文は省略できない。条件式に書いた式の評価結果はブーリアン型に型変換される。

 

13 switch-case文

switch-case文はif-else文と異なる構文を持つ条件分岐文である。伝統的に「case式:」の部分をcaseラベル、「default:」の部分をdefaultラベルと呼ぶ。switch文の中にcaseラベルは複数記述できる。defaultラベルはswitch文の中にただ1つ書ける。defaultラベルは省略可能である。

 

14 繰り返し文

繰り返し処理とは、ある条件が成立している間同じ処理を繰り返し実行する制御構造である。条件分岐と並ぶ制御構造の基本である。ソースコード上、同じ箇所を何度も回ることからループ(loop)処理とも呼ぶ。JavaScriptの繰り返し文は5種類ある。

 

15 while文

while文は繰り返し処理の最も基本的な文である。while文はwhileループとも呼ぶ。if-else文と同様に条件式に書いた式の評価結果はブーリアン型に型変換される。無限ループせずwhileループを抜けるには、ループ内で条件式が偽になる場合を保証する、break文を書く、return文を書く、例外を投げるという4つの方法がある。

 

16 do-while文

do-while文は別の繰り返し構文である。while文とdo-while文の違いは、条件式の評価を先に行うか、文の実行を先に行うかだけである。現場のプログラミングでは、do-while文は限定的な利用で、while文の方が多く使われる。事実上以下の2つだけである。

  • 文を少なくとも1回実行しないと、条件式の評価に意味が出ない場合
  • 文を少なくとも1回実行することを保証したい場合

 

17 for文

for文は別の繰り返し構文である。一般にforループと呼ばれる。「for (初期化式;条件式;更新式) 文」と表され、3つの式のどれもが省略可能である。初期化式には、一般にi=0のような変数の初期化の式を書く。初期か式で初期化する変数をループ変数と呼ぶ慣習がある。条件式の役割はwhile文やdo-while文の条件式と同じである。更新式には任意の式を書ける。多くの場合、ループ変数を更新する式を書く。

 

for文のイディオム

for文の主な用途は、ある値の範囲を最初から最後までなめる処理である。0から9までの10個の数字を出力する有名なイディオムは以下の通り。
for (var i = 0; i < 10; i++) {
}

 

18 for in文

for in文はオブジェクトのプロパティ名を列挙する繰り返し文である。
for (変数 in オブジェクト式)

inの左側には代入先に使える式を書く。文法的には左辺値を書く。inの右側にはオブジェクト型の式を書く。オブジェクト式に書いたオブジェクトのプロパティ名の文字列がループ変数に順々に代入される。

 

配列とfor in文

配列もオブジェクトでインデックスの数値がプロパティ名に相当するため、for in文で列挙できるが推奨しない。

 

for in文に関する注意点

  • プロパティを列挙する順序を意識しない
  • 列挙できないプロパティがある
  • プロトタイプ継承したプロパティも列挙する

 

19 for each in文

for each in文はECMAScriptには存在しないJavaScript独自拡張である。for inと異なり、変数にプロパティ名ではなくプロパティ値が代入される。

 

20 break文

break文はループ処理の途中でループを抜けたい場合に使う。

 

21 continue文

ループの中にcontinue文を書くと、それ以降のループ内の文をスキップしてループの条件式の評価に戻る。continue文を使うことでインデントを1段節約できる。

 

22 ラベルを使ったジャンプ

入れ子になったループをbreak文で抜けると、抜けるのは内部のループだけである。入れ子のループを同時に抜けるためにラベルを使える。ラベル文字列には任意の識別子を書ける。また、多くの場合繰り返し文に指定する。

 

23 return文

return文は関数の処理を中断し、指定した式の評価値を関数の返り値にする。式がない場合、関数の返り値はundefined値である。

 

24 例外

throw文で例外オブジェクト(例外値)を投げられる。式には任意の方の式を書ける。例外を捕捉する側はtry-catch-finally構文を使う。catch節とfinally節の片方だけの省略は可能である。

 

25 その他

with文は一時的に名前(変数名や関数名)の解決順序を変更するために使う。with文に与える式の型はオブジェクト型である。なおECMAScript第5版のstrictモードはwith文を禁止している。

 

26 コメント

コメントは「// 1行コメント」と「/* コメント *」の2種類存在する。

 

27 式

式(expression)の直感的な理解は計算式をイメージして得られる。「演算子とオペランド(被演算子)をつなげたもの」と言える。

 

28 演算子

JavaScriptの演算子を優先順序の順に並べると以下の通り。

  • . [] new
  • ()
  • ++ –
  • ! ~ +(単項) -(単項) typeof void delete
  • % * /
  • +(2項) -(2項)
  • << >> >>>
  • < <= > >=
  • == !== ===
  • &
  • ^
  • ¡
  • &&
  • !!
  • ?(3項)
  • = ÷= -= *= /= %= <<= >>= >>>= &= ^= ¡=
  • ,

 

29 式の評価

歴史的に文を実行する(execute)というのに対し、式を評価する(evaluate)という。式の評価は、基本的にオペランド(の式)を先に評価してから演算子を適用する。式の評価順序は以下の通り。

  • &&演算子、¡¡演算子、?:演算子の3つの演算子を除いてオペランドを演算前に評価する
  • オペランドは左のオペランドから評価する
  • メソッドおよびコンストラクタ呼び出し式では、呼び出し前に引数を左から評価する
  • カッコ内は優先して評価する
  • オペランドの評価中に例外が発生すると、残りのオペランドは評価しない
  • メソッドおよびコンストラクタ呼び出し式の途中の引数の評価で例外が発生すると、残りの引数は評価しない

 

30 演算子の優先順序と結合規則

同じ優先順序の演算子の間では、演算子の結合規則により演算の順序が決まる。結合規則は左結合か右結合かのいずれかである。結合規則は以下の5つがある。

  • 前置単項演算子は右結合
  • 後置単項演算子は左結合
  • 代入演算子以外の2項演算子は左結合
  • 代入演算子は右結合
  • 3項演算子は右結合

 

31 算術演算子

算術演算子は以下の11個にまとめられる。オペランドが数値以外であれば数値に型変換してから演算する。演算結果は数値である。

  • +:加算
  • -:減算
  • *:乗算
  • /:除算
  • %:剰余
  • ++(前置):インクリメント
  • ++(後置):インクリメント
  • –(前置):デクリメント
  • –(後置):デクリメント
  • -(単項):符号を反転
  • +(単項):符号をそのまま

前置演算子と後置演算子の違いは、評価値の違いである。前置演算子の評価値は加算や減算を行った後の値になり、後置演算子の評価値はその前の値になる。

 

32 文字列連結演算子

+演算子と+=演算子の2つの文字列連結演算子がある。演算結果は文字列値である。オペランドが文字列型でなければ文字列型に型変換してから演算する。

 

33 同値演算子

JavaScriptには同値演算子が2つある。===と==である。それぞれに対応する否定演算子(!==と!=)もある。

 

34 比較演算子

>、<、<=、>=の4つの比較演算子がある。比較演算の演算結果はブーリアン値である。オペランドが両方数値型であれば数値としての大小比較をする。オペランドが両方文字列型であれば文字列値の中身をUnicodeのコードポイントで大小比較する。

 

35 in演算子

inはプロパティ存在判定演算子である。演算結果はブーリアン値である。

 

36 instanceof演算子

instanceofは型判定演算子である。演算結果はブーリアン値である。

 

37 論理演算子

論理演算子は以下の3つがある。「!:否定(NOT)」「&&:条件積(AND)」「¡¡:条件和(OR)」である。論理演算はオペランドがブーリアン値以外であれば、ブーリアン型に型変換してから演算する。しかし他のプログラミング言語の経験者の直感に反するため、この動作への依存は推奨しない。

 

38 ビット演算子

ビット演算子は以下の7つがある。オペランドが数値以外であれば数値に型変換かつ内部的に32ビットの整数に変換してから演算する。演算結果は数値である。

  • &:ビット積(AND)
  • ¡:ビット和(OR)
  • ^:排他的ビット和(XOR)
  • <<:左シフト
  • >>:右シフト(最左ビットは符号維持の値)
  • >>>:右シフト(最左ビットをゼロにする)
  • ~:単項演算子。1の補数

 

39 代入演算子

代入演算子は変数に値を代入する=である。代入式は演算結果を持つ。演算結果は代入値である。しかし、書き間違えが頻発しているため代入式を条件式に書くのは推奨できない。

 

40 算術代入演算子

算術代入は+=や-=などである。算術演算子と=を並べて書いた演算子である。算術演算の結果を代入する。式の演算結果は代入値である。

 

41 条件演算子(3項演算子)

条件演算子は唯一の3項演算子である。&&演算子と||演算子と並びオペランドを遅延評価する演算子である。

 

42 typeof演算子

typeofは単項の型判定演算子である。オペランドの型は任意である。演算結果はオペランドの型を示す文字列値である。

 

43 new演算子

newは単項のオブジェクト生成演算子である(詳細は後述)。

 

44 delete演算子

deleteは単項のプロパティ削除演算子である。オペランドで指定したプロパティをオブジェクトから削除する。delete演算の演算結果はブーリアン値である。

 

45 void演算子

voidは単項のundefined演算子である。オペランドに何を渡しても演算結果はundefined値になる。

 

46 カンマ(,)演算子

,文字を使う2項のカンマ演算子がある。左オペランド、右オペランドの順で評価する。カンマ式の演算結果は右オペランドの値である。このため演算結果の型はオペランドに依存する。

 

47 ドット演算子とブラケット演算子

.(ドット)文字を使うドット演算子と[]を使うブラケット演算子がある。オブジェクトのプロパティにアクセスする演算子である。左オペランドがオブジェクト参照、右オペランドがプロパティ名である。

 

48 関数呼び出し演算子

( )を使う関数呼び出し演算子がある。左オペランドは関数で、右オペランドは関数に渡す引数(実引数)である。

 

49 演算子と型変換の注意点

  • +演算子:文字列連結を数値の加算より優先
  • 比較演算子(<,>,<=,>=):数値比較を文字列比較より優先

 

最後に

JavaScriptの文法規則 文、式、演算子についてまとめた。

JavaScriptのソースコードは文の集まりである。文は文と式から構成される。式は式と演算子から構成される。 式を最後まで分解すると、識別子(変数名や関数名)とリテラル値(数値や文字列の直接表記)と演算子(記号が予約語)になる。プログラミング言語における文は、その言語の文法で明確に定義された構文規則で決まる。式は演算子とオペランドをつなげたものである。

 

次回は、オブジェクト指向言語 変数とオブジェクトについてまとめる。

パーフェクトJavaScript (PERFECT SERIES 4)


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>