第二章JavaScript词法结构

第二章JavaScript词法结构

本章主要讲解js的词法结构

  • 区分大小写,空格和换行符
  • 注释
  • 字面量
  • 标识符和保留字
  • Unicode
  • 可选的分号

JavaScript程序文本

js区分大小写。这意味着,他的关键字,变量,函数名和其他标识符必须始终保持一致的大小写形式。比如,while关键字必须写成“while".

javascript忽略程序记号(token)之间的空格,js也忽略换行符,因为可以在程序中随意使用空格和换行,所以可以按照便于阅读的方式对程序进行格式化和缩进。

处理常规空格(\u0020),js也将制表符,各种Ascii控制符和Unicode间格识别为空格。js将换行符,回车符和回车/换行序列识别为行终止符。

注释

js支持两种注释:单行注释是以//开头到一行末尾的内容;多行注释位于/**/内的,可以跨行,下面都是合法的js注释:

// 这是注释 单行
/*这也是注释 多行
*/

字面量

字面量(literal)是一种直接出现在程序中的数据值.下面都是字面量.

  • 12 数值12
  • 1.2 数值1.2
  • “hello world” 字符串
  • ‘hi’ 另一个字符串
  • true 布尔值
  • null 无对象

标识符和保留字

简单来说,标识符就是一个名字,在js中,标识符用于在js代码中命名,常量,变量,属性,函数和类,以及为某些循环提供标记(label).

js标识符必须以字母,下划线,或美元开头,(数字不能作为第一个字符,以便js区分标识符和数值),以下都是合法的

i
my_variable
_dummy
$str

与其他语言一样,js为语言为语言自身使用而保留了某些标识符.这些**(保留字)**不能作为常规标识符使用,下面介绍保留字

保留字

as const export get null target void
async continue extends if of ths while
await debugger false import return throw with
break default fainlly in set true yield
case delete for instanceof static try 
catch do from let super typeof
class else function new switch var

js也保留或限制对某些关键字的使用,这些关键字当前并没有被语言所用,但是未来某个版本有可能会使用到.

enum implements interface package private protected public

由于历史原因,某些情况下也不允许使用argumenteval作为标识符,因此最好不要使用

Unicode

js程序是使用Unicode字符集编写的,因此在字符串和注释中可以使用任意Unicode字符,考虑到可移植性和易于编辑,建议在标识符中使用ASCII字母和数字,但是这只是一个编程惯例,语言本身支持在标识符中使用Unicode字母,数字和象形文字(但不支持表情符号).这意味着常量或变量的名字中可以包含数学符号或非英语文字:

const n = 23.1
const \(^o^)/~ = true

Unicode转义序列

某些计算机硬件和软件无法显示,输入和正确处理全部Unicode字符.为了方便程序员编码和支持使用老技术的系统,js定义了转义序列,从而可以仅使用ascii字符来表示unicode字符,这些Unicode转义序列以\u开头,后跟4位十六进制数字(包括大写或小写的字母AF)或包含在一对花括号内的16位十六进制数字.Unicode转义序列可以出现在js字符串字面量,正则表达式字面量和标识符中(不能出现在语言关键字中).

let café = 1 
caf\u00e9 // 1

js早期版本只支持4位数字转义序列,带花括号的版本是es6新增的,目的是更好地支持大小16位的Unicode码点,比如表情符号:

console.log("\u{1F600}")

Unicode转义序列也可以出现在注释中,但因为注释会被忽略,所以注释中的转义序列会被作为ASCII字符处理,不会被解释为Unicode.

Unicode归一化

如果你在程序中使用了非ASCII字符,那必须知道Unicode允许用多种编码方式同一个字符,加入字符串"é"可以被编码为一个Unicode字符\u00e9,也可以被编码为一个常规ASCII字符"e"后跟一个重音组合标记\u0301.这两种编码在文本编辑器中看看来完全相同,但是他们的二进制编码不同,因此js认为他们不同,而这可能导致非常麻烦的问题:

const café = 1 // 这个常量名为"caf\u{e9}
const café = 2 // "caf\u{301}"
café // 1
café // 2

Unicode标准为所有字符定义了首选编码并规定了归一化历程,用于把文本转换为适合比较的规范形式,js假定解释的源代码已经归一化,他自己不会执行任何归一化,如果你想在js程序中使用Unicode字符,应该保证使用自己的编辑器或其他工具对自己的源代码执行Unicode归一化,以防止其中包含看起来一样但实际不同的标识符.

可选的分号

与很多编程语言一样,js使用分号(😉,分割语句(参考第五章).这对于保持代码清晰很重要:如果没有分隔符,一条语句的结尾可能是另一条语句的开头,反之亦然.在js中,如果两条语句分别写在两行,通过可以省略他们之间的分号.另外在程序末尾,如果接下来的记号是右花括号},那么也可以略分号.

很多js程序员(包括本书中的代码示例)使用分号明确标识语句结束,即便这些分号并非必须.另一种风格是近可能省略分号,只要在极少数必要情况下采用.无论使用那种风格.都需要了解一些关于js中可选分号的细节.

a = 3;
b = 4;
a = 3;b=4;// 这种代码不能省略分号

注意js并非任何时候都把换行符当做分号,而只是在不隐式添加分号就无法解析代码情况下才这样做.更准确地讲,js只在下一个非空格字符无法被解释为当前语句的一部分时才把换行符当做分号

let  a
a
=
3
console.log(a);
// js 将上面代码解析为
let a;a = 3;console.log(a);

之所以把第一个换行符当做分号,是因为如果没有分号,js就无法解析代码let a a,第二个a本身是一条独立的语句,但js并没有吧第二个换行符当做分号,因为他还可以继续解析更长的语句a=3;

这些语句终止规则会导致某些意外情形.以下代码看起来是两条位于两行的语句:

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

但第二行的圆括号可以被解析为第一行f的函数调用,所以js将这两行代码解释为:

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

而这很有可能不是代码作者的真实意图,为了保证代码被解释为两个语句,这里必须明确的添加一个分号.

通常,如果语句以(,[,/,+或-开头的,就有可能被解释为之前语句的一部分,实践中,以/,+和-开头的语句极少,但以(开头和[开头的语句则并不鲜见,至少在某些js编程风格下经常会看到.有的程序员喜欢在所有语句前面都防御性的添加一个分号,这样即使他前面的语句被修改,删掉了之前末尾的分号,也不会影响当前语句:

let x = 0
;[x,x+1,x+2].forEach(console.log) // 防御:保证这条语句独立

js在不能把第二行解析为第一行的连续部分时,对换行符的解释有三种例外情况.第一种设计return,throw,yield,breakcontinue语句(参考第五章)这些语句经常独立存在,但有时候,后面也会跟一个标识符或表达式.如果这几个单词后面(任何其他标记前面)有换行符,js就会把这个换行符解释为分号,例如,

return
true;

js推断

return;true;

你的意图

return true;

这意味着,一定不能在return,break或continue等关键字和他们后面的表达式之间加入换行符.如果加入了换行符,那代码出错后的调试会非常麻烦,因为不明显

第二种例外情况涉及++和–操作符.这些操作符既可以放在表达式前面,也可以反正表达式后面,如果想把这两个操作符作为后置操作符,那他们必须与自己操作的表达式位于同一行.第三种例外情况涉及使用简洁的"箭头"语法定于的函数:箭头=>必须跟参数列表在同一行.

小结

本章讲解了 如何编写JavaScript程序,下一章将提升一个层次,

介绍 程序基本介绍单位的原始类型和值(数值,字符串,等等)

本文链接:https://my.lmcjl.com/post/6703.html

展开阅读全文

4 评论

留下您的评论.