天天看點

重學前端 27 # JavaScript的詞法

說明

每天10分鐘,重構你的前端知識體系專欄筆記。

一、JavaScript 的詞法(lexical grammar)

​ECMAScript 源碼文本​

​​會被從左到右掃描,并被轉換為一系列的輸入元素,包括 ​

​token、控制符、行終止符、注釋和空白符​

​。ECMAScript 定義了一些關鍵字、字面量以及行尾分号補全的規則。

​​可以參考MDN文檔–詞法文法​​

1.1、分類

  • ​WhiteSpace​

    ​ 空白字元
  • ​LineTerminator​

    ​ 換行符
  • ​Comment​

    ​ 注釋
  • ​Token​

    ​ 詞
  • ​IdentifierName 辨別符名稱​

    ​:典型案例就是使用的變量名,注意這裡關鍵字也包含在内。
  • ​Punctuator 符号​

    ​:使用的運算符和大括号等符号。
  • ​NumericLiteral 數字直接量​

    ​:就是寫的數字。
  • ​StringLiteral 字元串直接量​

    ​:就是用單引号或者雙引号引起來的直接量。
  • ​Template 字元串模闆​

    ​:用反引号 ` 括起來的直接量。

1.2、特别之處

1、除法和正規表達式沖突問題

JavaScript 不但支援除法運算符​

​/​

​​和​

​/=​

​​,還支援用斜杠括起來的正規表達式​

​/.../​

​。

解決方案:是定義兩組詞法,然後靠文法分析傳一個标志給詞法分析器,讓它來決定使用哪一套詞法。

2、字元串模闆

理論上,​

​${ }​

​​内部可以放任何 ​

​JavaScript 表達式代碼​

​​,而這些代碼是以 ​

​}​

​​ 結尾的,也就是說,這部分詞法不允許出現 ​

​}​

​ 運算符。
// <!-- 模闆文法 -->
`Hello, ${world}`      

3、四種詞法定義

  • InputElementDiv
  • InputElementRegExp
  • InputElementRegExpOrTemplateTail
  • InputElementTemplateTail

二、空白符号 Whitespace

2.1、空白符号分類

  • ​<HT>​

    ​​(或稱​

    ​<TAB>​

    ​​) 是​

    ​U+0009​

    ​​,是縮進​

    ​TAB​

    ​​ 符,字元串中寫的​

    ​\t​

    ​ 。
  • ​<VT>​

    ​​是​

    ​U+000B​

    ​​,也就是垂直方向的​

    ​TAB 符 \v​

    ​。
  • ​<FF>​

    ​​是​

    ​U+000C​

    ​​,​

    ​Form Feed​

    ​​,分頁符,字元串直接量中寫作​

    ​\f​

    ​。
  • ​<SP>​

    ​​是​

    ​U+0020​

    ​,就是最普通的空格。
  • ​<NBSP>​

    ​​是​

    ​U+00A0​

    ​​,非斷行空格,它是​

    ​SP​

    ​ 的一個變體,在文字排版中,可以避免因為空格在此處發生斷行,其它方面和普通空格完全一樣。
  • ​<ZWNBSP>​

    ​​(舊稱​

    ​<BOM>​

    ​​) 是​

    ​U+FEFF​

    ​​,這是​

    ​ES5​

    ​​ 新加入的空白符,是​

    ​Unicode​

    ​​中的零寬非斷行空格,在以​

    ​UTF 格式​

    ​​編碼的檔案中,常常在檔案首插入一個額外的​

    ​U+FEFF​

    ​​,解析​

    ​UTF 檔案​

    ​​的程式可以根據​

    ​U+FEFF​

    ​​ 的表示方法猜測檔案采用哪種​

    ​UTF 編碼​

    ​​方式。這個字元也叫做​

    ​bit order mark​

    ​。

2.2、所有的 Unicode 中的空格分類

重學前端 27 # JavaScript的詞法

三、換行符 LineTerminator

3.1、四種換行符

  • ​<LF>​

    ​​:是​

    ​U+000A​

    ​​,就是最正常換行符,在字元串中的​

    ​\n​

  • ​<CR>​

    ​​:是​

    ​U+000D​

    ​​,這個字元真正意義上的​

    ​回車​

    ​​,在字元串中是​

    ​\r​

  • ​<LS>​

    ​​:是​

    ​U+2028​

    ​​,是​

    ​Unicode​

    ​ 中的行分隔符。
  • ​<PS>​

    ​​:是​

    ​U+2029​

    ​​,是​

    ​Unicode​

    ​ 中的段落分隔符。

注意:換行符會影響 JavaScript 的兩個重要文法特性:​

​自動插入分号​

​​ 和 ​

​no line terminator​

​規則。

四、注釋 Comment

// 多行注釋
/* MultiLineCommentChars */ 

// 單行注釋
// SingleLineCommentChars      

五、辨別符名稱 IdentifierName

​IdentifierName​

​​可以以​

​美元符$​

​​,​

​下劃線_​

​​或者 ​

​Unicode 字母​

​​開始,除了開始字元以外,還可以使用 ​

​Unicode​

​ 中的連接配接标記、數字、以及連接配接符号。

關鍵字

await break case catch class const 
continue debugger default delete do else 
export extends finally for function if 
import ininstance of new return super 
switch this throw try typeof 
var void while with yield      
// 為了未來使用而保留的關鍵字
enum

// 在嚴格模式下還有
implements package protected 
interface private public      

​NullLiteral(null)和 BooleanLiteral(true false)​

​ 也是保留字。

僅當不是保留字的時候,​

​IdentifierName​

​​會被解析為​

​Identifier​

​。

六、符号 Punctuator

{ ( ) [ ] . ... ; , < > <= >= == != === !== 
+ - * % ** ++ -- << >> >>> & | ^ ! ~ && || 
? : = += -= *= %= **= <<= >>= >>>= &= |= 
^= => / /= }      

七、數字直接量 NumericLiteral

JavaScript 規範中規定的數字直接量可以支援四種寫法:十進制數、二進制整數、八進制整數和十六進制整數。

1、十進制的 Number 可以帶小數,小數點前後部分都可以省略,但是不能同時省略

.01    // 0.01
12.    // 12
12.01  // 12.01      

2、12.toString() 為什麼會報錯?

12.toString()
// Uncaught SyntaxError: Invalid or unexpected token

// 原因: `12.` 會被當做省略了小數點後面部分的數字而看成一個整體,相當于執行了12toString(),是以會報錯

// 解決:加入空格讓其單獨成為一個 token

12 .toString()  // "12"

// 或者加一個.

12..toString()  // "12"      

另外科學計數法跟進制就不寫了。。。。

八、字元串直接量 StringLiteral

// 雙引号
" DoubleStringCharacters "

// 單引号
' SingleStringCharacters '      

8.1、單字元轉義

即一個反斜杠 ​

​\​

​ 後面跟一個字元這種形式。
重學前端 27 # JavaScript的詞法

九、正規表達式直接量 RegularExpressionLiteral

正規表達式由 Body 和 Flags 兩部分組成
/RegularExpressionBody/g      

其中 Body 部分至少有一個字元,第一個字元不能是 (因為 / 跟多行注釋有詞法沖突)。

十、字元串模闆 Template

`a${b}c${d}e`

/*
// 被拆成了五個部分

`a${  //  這個被稱為模闆頭
b     //  普通辨別符
}c${  //  被稱為模闆中段
d     //  普通辨別符
}e`   //  被稱為模闆尾

*/      
function kaimo(){
    console.log(arguments);
}

var temp = "kaimo"

kaimo`hello ${temp} !`

// [["hello ", " !"], "kaimo"]      

繼續閱讀