《重学前端》学习笔记(7)

JavaScript 的文法:词法

文法是编译原理中对语言的写法的一种规定,一般来说,文法分成词法和语法两种。

词法规定了语言的最小语义单元:token,可以翻译成“标记”或者“词”,在此专栏文章中,统一把 token 翻译成词。

从字符到词的整个过程是没有结构的,只要符合词的规则,就构成词,一般来说,词法设计不会包含冲突。词法分析技术上可以使用状态机或者正则表达式来进行。

概述

先看 JavaScript 的词法定义。JavaScript 源代码中的输入可以这样分类:

  • WhiteSpace 空白字符

  • LineTerminator 换行符

  • Comment 注释

  • Token 词

    • IdentifierName 标识符名称,典型案例是我们使用的变量名,注意这里关键字也包含在内了。
    • Punctuator 符号,我们使用的运算符和大括号等符号。
    • NumericLiteral 数字直接量,就是我们写的数字。
    • StringLiteral 字符串直接量,就是我们用单引号或者双引号引起来的直接量。
    • Template 字符串模板,用反引号` 括起来的直接量

这个设计符合比较通用的编程语言设计方式,不过,JavaScript 中有一些特别之处,下面讲特别在哪里。

  • 除法和正则表达式冲突问题

    JavaScript 不但支持除法运算符“/”和“/=”,还支持用斜杠括起来的正则表达式“/abc/

    但是,这时候对词法分析来说,其实是没有办法处理的,所以 JavaScript 的解决方案是定义两组词法,然后靠语法分析传一个标志给词法分析器,让它来决定使用哪
    一套词法。

  • 是字符串模板

    模板语法大概是这样的:

    `Hello, ${name}`
    

    理论上,“ ${ } ”内部可以放任何 JavaScript 表达式代码,而这些代码是以“ } ” 结尾的,也就是说,这部分词法不允许出现“ } ”运算符。

是否允许“ } ”的两种情况,与除法和正则表达式的两种情况相乘就是四种词法定义,所以你在 JavaScript 标准中,可以看到四种定义:

  • InputElementDiv;
  • InputElementRegExp;
  • InputElementRegExpOrTemplateTail;
  • InputElementTemplateTail。

为了解决这两个问题,标准中还不得不把除法、正则表达式直接量和“ } ”从 token 中单独抽出来,用词上,也把原本的 Token 改为 CommonToken。在本文档,我们依然把它们归类到 token 来理解。

对一般的语言的词法分析过程来说,都会丢弃除了 token 之外的输入,但是对 JavaScript 来说,不太一样,换行符和注释还会影响语法分析过程,这个将会在语法部分详细讲解(所以要实现 JavaScript 的解释器,词法分析和语法分析非常麻烦,需要来回传递信息)。

空白符号 Whitespace

说起空白符号,想必给大家留下的印象就是空格,但是实际上,JavaScript 可以支持更多空白符号。

  • <HT>(或称<TAB>) 是 U+0009,是缩进 TAB 符,也就是字符串中写的 \t 。
  • <VT>是 U+000B,也就是垂直方向的 TAB 符\v,这个字符在键盘上很难打出来,所以很少用到。
  • <FF>是 U+000C,Form Feed,分页符,字符串直接量中写作 \f,现代已经很少有打印源程序的事情发生了,所以这个字符在 JavaScript 源代码中很少用到。
  • <SP>是 U+0020,就是最普通的空格了。
  • <NBSP>是 U+00A0,非断行空格,它是 SP 的一个变体,在文字排版中,可以避免因为空格在此处发生断行,其它方面和普通空格完全一样。多数的 JavaScript
    编辑环境都会把它当做普通空格(因为一般源代码编辑环境根本就不会自动折行……)。HTML 中,很多人喜欢用的 最后生成的就是它了。
  • <ZWNBSP>(旧称<BOM>) 是 U+FEFF,这是 ES5 新加入的空白符,是 Unicode 中的零宽非断行空格,在以 UTF 格式编码的文件中,常常在文件首插入一个额外的
    U+FEFF,解析 UTF 文件的程序可以根据 U+FEFF 的表示方法猜测文件采用哪种 UTF 编码方式。这个字符也叫做“bit order mark”。
    此外,JavaScript 支持所有的 Unicode 中的空格分类下的空格.

换行符 LineTerminator

接下来我们来看看换行符,JavaScript 中只提供了 4 种字符作为换行符。

  • <LF>
  • <CR>
  • <LS>
  • <PS>

其中,<LF>是 U+000A,就是最正常换行符,在字符串中的\n

<CR>是 U+000D,这个字符真正意义上的“回车”,在字符串中是\r,在一部分 Windows 风格文本编辑器中,换行是两个字符\r\n
<LS>是 U+2028,是 Unicode 中的行分隔符。<PS>是 U+2029,是 Unicode 中的段落分隔符。
大部分 LineTerminator 在被词法分析器扫描出之后,会被语法分析器丢弃,但是换行符会影响 JavaScript 的两个重要语法特性:自动插入分号和“no line terminator”规则。

注释 Comment

JavaScript 的注释分为单行注释和多行注释两种:

/* MultiLineCommentChars */
// SingleLineCommentChars

多行注释中允许自由地出现MultiLineNotAsteriskChar,也就是除了*之外的所有字符。而每一个*之后,不能出现正斜杠符/
除了四种 LineTerminator 之外,所有字符都可以作为单行注释。
我们需要注意,多行注释中是否包含换行符号,会对 JavaScript 语法产生影响,对于“no line terminator”规则来说,带换行的多行注释与换行符是等效的。

标识符名称 IdentifierName

  • IdentifierName可以以美元符$下划线_或者 Unicode 字母开始,除了开始字符以外,IdentifierName中还可以使用 Unicode 中的连接标记、数字、以及连接符
    号。
  • IdentifierName的任意字符可以使用 JavaScript 的 Unicode 转义写法,使用 Unicode 转义写法时,没有任何字符限制。
  • IdentifierName可以是IdentifierNullLiteralBooleanLiteral或者keyword,在ObjectLiteral中,IdentifierName还可以被直接当做属性名称使用。仅当不是保留字的时候,IdentifierName会被解析为Identifier
    注意<ZWNJ><ZWJ>是 ES5 新加入的两个格式控制字符,它们都是 0 宽的。

(这节没看完…)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值