二.JavaScript词法结构

184 阅读6分钟

1.词法结构

编程语言的词法结构是一套基础性规则,用来描述如何使用这门语言来编写程序。作为语法的基础,它规定了诸如变量名是什么样的、怎么写注释,以及程序语句之间如何分隔等规则。

2.字符集

JavaScript程序是用Unicode字符集编写的。Unicode是ASCII和Latin-1的超集,并支持地球上几乎所有在用的语言。

2.1 区分大小写

JavaScript是区分大小写的语言。也就是说,关键字、变量、函数名和所有的标识符(identifier)都必须采取一致的大小写形式。

2.2 空格、换行符和格式控制符

JavaScript会忽略程序中标识(token)之间的空格。多数情况下,JavaScript同样会忽略换行符.

除了可以识别普通的空格符(\u0020),JavaScript还可以识别如下这些表示空格的字符:水平制表符(\u0009)、垂直制表符(\u000B)、换页符(\u000C)、不中断空白(\u00A0)、字节序标记(\uFEFF),以及在Unicode中所有Zs类别的字符。

JavaScript将如下字符识别为行结束符:换行符(\u000A),回车符(\u000D),行分隔符(\u2028),段分隔符(\u2029)。回车符加换行符在一起被解析为一个单行结束符。

2.3 Unicode转义序列

JavaScript定义了一种特殊序列,使用6个ASCII字符来代表任意16位Unicode内码。这些Unicode转义序列均以\u为前缀,其后跟随4个十六进制数(使用数字以及大写或小写的字母A~F表示)。这种Unicode转义写法可以用在JavaScript字符串直接量、正则表达式直接量和标识符中(关键字除外)。例如,字符é的Unicode转义写法为\u00E9

"café"==="caf\u00e9"  //=>true

Unicode转义写法也可以出现在注释中,但由于JavaScript会将注释忽略,它们只是被当成上下文中的ASCII字符处理,而且并不会被解析为其对应的Unicode字符。

3. 注释

注释是给开发人员看到,JavaScript引擎会自动忽略

JavaScript支持两种格式的注释。在行尾“//”之后的文本都会被JavaScript当做注释忽略掉的。此外,“/”和“/”之间的文本也会当做注释,这种注释可以跨行书写,但不能有嵌套的注释。下面都是合法的JavaScript注释:

//这里是单行注释
/*这里是一段注释*///这里是另一段注释

/*
*这又是一段注释
*这里的注释可以连写多行
*/

/**声明语句上边的注释内容,会在鼠标经过时提示,可以用来备注函数用途和对象属性含义 */

image.png

image.png

4. 直接量

所谓直接量(literal),就是程序中直接使用的数据值。下面列出的都是直接量:

12  //数字
1.2  //小数
"hello world"  //字符串文本
'Hi'  //另一个字符串
true  //布尔值
false  //另一个布尔值
/javascript/gi   //正则表达式直接量(用做模式匹配)
null   //空
{x:1,y:2}  //对象直接量
[1,2,3,4,5]  //数组

5. 标识符和保留字

标识符(identifier)就是一个名字,指的是用来识别各种值的合法名称。最常见的标识符就是变量名,以及后面要提到的函数名。JavaScript 语言的标识符对大小写敏感,所以aA是两个不同的标识符。

标识符有一套命名规则,不符合规则的就是非法标识符。JavaScript 引擎遇到非法标识符,就会报错。

  • 第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号($)和下划线(_)(数字是不允许作为首字符出现的,以便JavaScript可以轻易区分开标识符和数字)。
  • 第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字0-9。 下面是合法的标识符:
i
my_variable_name
v13
_dummy
$str

程序员也可以使用非英语语言或数学符号来书写标识符:

var sí=true;
var π=3.14;

image.png

和其他任何编程语言一样,JavaScript保留了一些标识符,拿出来用做自己的关键字

JavaScript的具体实现可能定义独有的全局变量和函数,每一种特定的JavaScript运行环境(客户端、服务器端等)都有自己的一个全局属性列表,应当避免把它们的名字用做变量名和函数名。

6. 可选的分号

JavaScript的语法和Java语言类似,每个语句以;结束,语句块用{...}。但是,JavaScript并不强制要求在每个语句的结尾加;,浏览器中负责执行JavaScript代码的引擎会自动在每个语句的结尾补上;

需要注意的是,JavaScript并不是在所有换行处都填补分号:只有在缺少了分号就无法正确解析代码的时候,JavaScript才会填补分号。换句话讲(类似下面代码中的两处异常),如果当前语句和随后的非空格字符不能当成一个整体来解析的话,JavaScript就在当前语句行结束处填补分号。

var
a
=
3
console.log(a);

JavaScript引擎将其解析为:

var a;a=3;console.log(a);

avaScript给第一行换行处添加了分号,因为如果没有分号,JavaScript就无法解析代码var a a。第二个a可以单独当做一条语句"a;",但JavaScript并没有给第二行结尾填补分号,因为它可以和第三行内容一起解析成“a=3;”。

image.png 让JavaScript引擎自动加分号在某些情况下会改变程序的语义,导致运行结果与期望不一致。

这段代码写成了两行,看起来是两条独立的语句:

var y=x+f
(a+b).toString()

但第二行的圆括号却和第一行的f组成了一个函数调用,JavaScript会把这段代码看做:

var y=x+f(a+b).toString();

image.png

如果当前语句和下一行语句无法合并解析,JavaScript则在第一行后填补分号,这是通用规则,但有两个例外。第一个例外是在涉及return、break和continue语句的场景中。如果这三个关键字后紧跟着换行,JavaScript则会在换行处填补分号。

return
true;

JavaScript会解析成:

return; true;

image.png 也就是说,在return、break、continue和随后的表达式之间不能有换行。

第二个例外是在涉及“++”和“--”运算符的时候。这些运算符可以作为表达式的前缀,也可以当做表达式的后缀。如果将其用做后缀表达式,它和表达式应当在同一行。否则,行尾将填补分号,同时“++”或“--”将会作为下一行代码的前缀操作符并与之一起解析,例如,这段代码:

x
++
y

这段代码将解析为"x;++y",而不是"x++;y"。

image.png