Lexical grammar
此篇介紹 Javascript 的 lexical grammar。ECMAScript 的原始碼從左到右被掃描並被轉換成一系列的輸入元素也就是 token、控制字元、行終止字元、註解或是空白字元。ECMAScript 也定義了一些特定的關鍵字和實體語法還有用來自動插入分號來結束陳述式的規則。
控制字元
空白字元
行終止字元
註解
在 Javascript 程式中,註解通常被用來寫提示、註釋、建議或警告。這可以讓程式更好讀也更好理解,同時也是一個很好的除錯工具,可以讓一些程式碼不被執行。
Javascript 有兩種方式寫註解。
第一種是 //
; 它將在它之後的文本變成註解。例如:
function comment() {
// 這是一行 Javascript 註解
console.log("Hello world!");
}
comment();
第二種更有彈性的方式是 /* */
。
例如,你可以將它用在單行上:
function comment() {
/* 這是一行 Javascript 註解 */
console.log("Hello world!");
}
comment();
你也可以將它用來寫多行註解:
function comment() {
/* 這個註解可以跨越多行。注意只有當我們要結束註解時才寫
多行註解的終止符號 */
console.log("Hello world!");
}
comment();
如果你想要你也可以把它插在一行的中央,雖然它會讓你的程式變得難讀所以請謹慎使用:
function comment(x) {
console.log("Hello " + x /* 插入 x 的值 */ + " !");
}
comment("world");
此外,你也可以把一段程式用註解包起來讓它不被執行:
function comment() {
/* console.log('Hello world!'); */
}
comment();
在這個情況, console.log()
永遠不會被呼叫因為它在註解裡面。任意行數的程式碼都可以用這個方法來使之失去作用。
保留字
ECMAScript 2015 保留關鍵字
未來保留關鍵字
根據 ECMAScript 的規格,以下的關鍵字被保留供未來使用。他們目前沒有功用但未來可能有,所以不能將他們用作識別字。
以下關鍵字將永遠被保留:
enum
以下關鍵字只有在嚴格模式底下才被保留:
implements
interface
let
package
private
protected
public
static
以下關鍵字只有在出現在模組程式碼中時才被保留:
await
舊標準中的未來保留關鍵字
以下關鍵字在舊的 ECMAScript 規格中 (ECMAScript 1 到 3) 為未來保留關鍵:
abstract
boolean
byte
char
double
final
float
goto
int
long
native
short
synchronized
throws
transient
volatile
此外,如 null
, true
與 false
等實體語法 (literal) 在 ECMAScript 中不能被用作識別字。
保留字的使用
只有當用在識別字的時候保留關鍵字才會被保留 (相對於 IdentifierNames
) 。如 es5.github.com/#A.1 所述,以下保留關鍵字的用法都屬於IdentifierNames
因此是合法的。
a.import
a['import']
a = { import: 'test' }.
反之,以下用法不合法因為用在識別字上,識別字屬於 IdentifierName
但不包含保留字。識別字用在 FunctionDeclaration, FunctionExpression, VariableDeclaration
等等?。而 IdentifierName
被用在 MemberExpression, CallExpression
等等。
function import() {} // 不合法.
實體語法
Null
更多說明請參閱 null
。
null
布林值
更多說明請參閱 Boolean
。
true
false
數值
十進制
1234567890
42
// 謹慎使用前導零
0888 // 888 被解析成十進制
0777 // 被解析成八進制, 十進制值為 511
數值的實體語法可以可以以零 (0
) 為首再街上其他十進制數字。然而一但零後面的的數字都小於 8 時,這個數值會被解讀成八進制數字,這個行為不會丟出例外,請參閱 Firefox bug 957513。也請參閱 parseInt()
。
二進制
二進制數字的語法為一個起首零加上小寫或大小的拉丁字元「B」(0b
或 0B
)。因為這個語法是在 ECMAScript 2015 才新增的,請參閱底下的瀏覽器相容表。如果 0b
之後的數字不是 0 或 1,「0b 之後找不到二進制數字」的 SyntaxError
會被丟出。
0b10000000000000000000000000000000 // 2147483648
0b01111111100000000000000000000000 // 2139095040
0B00000000011111111111111111111111 // 8388607
八進制
八進制數字的語法為一個起首零加上小寫或大小的拉丁字元「O」(0o
或 0O
)。因為這個語法是在 ECMAScript 2015 才新增的,請參閱底下的瀏覽器相容表。如果 0o
之後的數字不是(01234567)其中之一,「0o 之後找不到八進制數字」的 SyntaxError 會被丟出。
0O755 // 493
0o644 // 420
十六進制
十六進制數字的語法為一個起首零加上小寫或大小的拉丁字元"X" (0x
或 0X
)。如果 0x
之後的數字不是 (0123456789ABCDEF) 其中之一,"識別字緊接在數值實體語法後"的 SyntaxError 會被丟出。
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
0x123456789ABCDEF // 81985529216486900
0XA // 10
物件
更多說明請參閱 Object
及 Object initializer。
var o = { a: "foo", b: "bar", c: 42 };
// 簡短表示法 (ES2015 新增)
var a = "foo",
b = "bar",
c = 42;
var o = { a, b, c };
// ES2015 以前必須這樣寫
var o = { a: a, b: b, c: c };
陣列
更多說明請參閱 Array
。
[1954, 1974, 1990, 2014]
字串
'foo'
"bar"
十六進制跳脫序列
"\xA9" // "©"
Unicode 跳脫序列
一個 Unicode 跳脫序列由 \u
接上 4 個十六進制的數值所組成。每一個十六進制的數值表示一個 UTF-16 編碼的 2 位元組字元。對於編碼位置在 0~FFFF 之間的字元,其 Unicode 表示法與編碼位置相同。而更高的編碼位置需要兩個跳脫序列來表示,又稱為代理對(surrogate pair),代理對表示的數值與編碼位置不同 (代理對計算規則 wiki)。
"\u00A9" // "©"
Unicode 跳脫編碼位置
ECMAScript 2015 新增。使用 Unicode 跳脫編碼位置表示法,即可使用與編碼位置完全相同的表示法 (最高到 0x10FFFF
) 而不受編碼位置高於 FFFF 需用代理對表示的限制。
更多說明請參閱 String.fromCodePoint()
或 String.prototype.codePointAt()
。
"\u{2F804}"
// 等價於代理對表示法
"\uD87E\uDC04"
正規表達式
更多說明請參閱 RegExp
。
/ab+c/g
// 一個空的正規表示法。
// 兩個斜線之間不得為空,否則將被視為單行註解。
/(?:)/
範本字串
更多說明請參閱 template strings 。
`string text`
`string text line 1
string text line 2`
`string text ${expression} string text`
tag `string text ${expression} string text`
自動插入分號
否些 JavaScript statements 必須以分號作結,因此會受到自動插入分號 (ASI) 規則影響。
- 空運算式
let
,const
, 變數宣告import
,export
, 模組宣告- 運算式
debugger
continue
,break
,throw
return
ECMAScript 規格闡明 自動插入分號的三個規則。
1. 如果 行終止字元 或 "}" 出現在不符文法的地方,一個分號會被自動插入在其之前。
{ 1 2 } 3
// 會被 ASI 轉換成
{ 1 2 ;} 3;
2. 當一個 token 輸入流到了結尾而解析器仍然無法將其解析為一個完整的程式,一個分號會被自動插入於其後。
在這裡 ++
並不會被當作作用於變數b
的 後綴運算元,因為行終止字元出現在b
和 ++
之間。
a = b
++c
// 會被 ASI 轉換成
a = b;
++c;
3. 當一個運算式中出現 restricted productions 後面接著一個行終止元,一個分號會被自動插入於行終止元之前。以下這些陳述式有"不允許出現行終止元"規則:
- 後綴運算式 (
++
and--
) continue
break
return
yield
,yield*
module
return
a + b
// 會被 ASI 轉換成
return;
a + b;
規格
Specification |
---|
ECMAScript Language Specification |
瀏覽器相容性
BCD tables only load in the browser