文档章节

词法结构

-愚公移山-
 -愚公移山-
发布于 2016/11/29 10:18
字数 2466
阅读 7
收藏 0

编程语言的词法结构是一套基础性规则,用来描述如何使用这门语言来编写程序。

字符集

JavaScript程序使用Unicode字符集编写的。Unicode是ASCII和Latin-1的超集,并支持地球上几乎所有在用的语言。ECMAScript3要求JavaScript的实现必须支持Unicode2.1即后续版本,ECMAScript5则要求支持Unicode3及后续版本。

区分大小写

JavaScript是区分大小写的语言。但需要注意的是,HTML并不区分大小写,尽管XHTML区分大小写。由于它和客户端JavaScript联系紧密,因此这点区别很容易被混淆。

空格,换行符和格式控制符

JavaScript会忽略程序中标识之间的空格。多数情况下,JavaScript同样会忽略换行符。由于可以在代码中随意使用空格和换行符,因此可以采用整齐,一致的缩进来形成统一的编码风格,从而提高代码的可读性。

除了可以识别普通的空格符(\u0020),JavaScript还可以识别如下这些可以表示空格的字符:水平制表符(\u0009),垂直制表符(\u000B),换页符(\u000C),不中断空白(\u00A0),字节序标记(\uFEFF),以及在Unicode中所有Zs类别的字符。JavaScript将如下字符识别为行结束符:换行符(\u000A),回车符(\u00D),段分隔符(\u2029).回车符加换行符在一起被解析为一个单行结束符。

Unicode格式控制字符(Cf类),比如“从右至左书写标记”(\u200F)和“从左至右书写标记”(\u200E),控制着文本的视觉显示,这对于一些非英语文本的正确显示来说是至关重要的,这些字符可以用在JavaScript的注释,字符串直接量和正则表达式直接量中,但不能用在标识符(如变量名)中。但有个例外,零宽连接符(\u200D)和零宽非连接符(\uFEFF)是可以出现在标识符中的,但不能作为标识符的首字符。上文也提到了,字节序标记格式控制符被当成了空格来对待。

Unicode转义序列

在有些计算机硬件和软件里,无法显示或输入Unicode字符全集。为了支持哪些使用老旧技术的程序员,JavaScript定义了一种特殊序列,使用6个ASCII字符来代表任意16位Unicode内码。这些Unicode转义序列均以\u为前缀,其后跟随4个十六进制数(使用数字以及大写或小写的字母A~F表示)。这种Unicode转义写法可以用在JavaScript字符串直接量,正则表达式直接量和标识符中(关键字除外)。如下两个JavaScript字符串是完全一样的:"café"==="caf\u00e9"  //==>true

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

标准化

Unicode允许使用多种方法对同一个字符进行编码。比如字符é可以使用Unicode字符\u00e9表示,也可以使用普通的ASCII字符e跟随一个语调符\u0301.在文本编辑器中,这两种编码显示的结果一模一样,但它们的二进制编码表示是不一样的,在计算机里也不相等。Unicode标准为所有字符定义了一个首选的编码格式,并给出了一个标准化的处理方式将文本转换为一种适合比较的标准格式,Javascript会认为它正在解析的程序代码已经是这种标准格式,不会再对其标识符,字符串或正则表达式做标准化处理。

注释

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

//这是单行注释

/*这是一段注释*/

/*

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

*/

直接量

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

12      //数字                       "hello,word!"    //字符串文本                  /javascript/gi   //正则表达式直接量

1.2    //小数                         true                 //布尔值                         null                 //空

{name:"lily",sex:"boy"}        //对象直接量               [1,2,3,4]              //数组直接量

标识符和保留字

标识符就是一个名字,在JavaScript中,标识符用来对变量和函数进行命名,或者用作JavaScript代码中某些循环语句中的跳转位置的标记。JavaScript标识符必须以字母,下划线(_),或美元符号($)开始,后续的字符可以是字母,数字,下划线或美元符号。数字不允许作为首字符出现,以便JavaScript可以轻松区分开标识符和数字。下面是合法的标识符:

i      my_name      v13      _a_boy    $str

出于可移植性和易于书写的考虑,通常我们只使用ASCII字母和数字来书写标识符。然而需要注意的是,JavaScript允许标识符中出现Unicode字符全集中的字母和数字。从技术上讲,ECMAScript标准也允许在标识符的首字符后面出现Unicode字符集中的Mn类,Mc类和Pc类。由此,程序员也可以使用非英语语言或数学符号来书写标识符:

var  π=3.14;              var  Š=true;

和其他任何编程语言一样,JavaScript保留了一些标识符为自己所用。JavaScript把一些标识符拿出来用作自己的关键字,因此,就不能在程序中把这些关键字用作标识符了:

break, delete, function, return, typeof, case, do, if, switch, var, catch, else, in, this, void, continue, false, instanceof, throw, while, debugger, finally, new, true, with, default, for, null, try

JavaScript同样保留了一些关键字,这些关键字在当前的版本中并没有使用,但在未来版本中可能会用到。

class, const, enum, export, extends, import, super

此外,下面这些关键字在普通的JavaScript代码中是合法的,但是在严格模式下是保留字:

implements, let, private, public, yield, interface, package, protected, static

严格模式同样对下面的标识符的使用做了严格限制,它们并不完全是保留字,但不能用作变量名,函数或参数名:arguments, eval

ECMAScript 3将java的所有关键字都列为自己的保留字,尽管这些保留字在ECMAScript5中放宽了限制,但如果你希望代码能在基于ECMAScript3实现的解释器上运行的话,应当避免使用这些关键字作为标识符:

abstract, double, goto, native, static, boolean, enum, implements, package, super, byte, export, import, private, synchronized, char, extends, int, protected, throws, class, final, interface, public, transient, const, float, long, short, volatile

JavaScript预定义了很多全局变量和函数,应当避免把它们的名字用作变量名和函数名:

arguments, encodeURI, Infinity, Number, RegExp, Array, encodeURIComponent, isFinite, Object, String, Boolean, Error, isNaN, parseFloat, SyntaxError, Date, eval, JSON, parseInt, TypeError, decodeURI, EvalError, Math, RangeError, underfined, decodeURIComponent, Function, NaN, ReferenceError, URIError

JavaScript的具体实现可能定义独有的全局变量和函数,每一种特定的JavaScript运行环境(客户端,服务器端等)都有自己的一个全局属性列表。

可选的分号

和其他许多编程语言一样,JavaScript使用分号将语句分隔开。这对增强代码的可读性和整洁性是非常重要的。在JavaScript中,如果语句各自独占一行,通常可以省略语句之间的分号(程序的结尾或右花括号'}'之前的分号也可以省略)。

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

var  a

a

=

3

console.log(a)

JavaScript将其解析为:var a; a=3; console.log(a);

这些语句的分隔规则会导致一些意想不到的情形,如下,这段代码写成了两行,看起来是两个独立的语句:

var  y=x+f

(a+b).toString()

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

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

而这段代码的本意并不是这样的。

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

return

true

JavaScript会解析为:return; true;

而代码的本意是这样的:return  true; 也就是说,在break, return, continue和随后的表达式之间不能有换行。如果添加了换行,程序只有在极特殊的情况下才会报错,而且程序的调试非常不方便。

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

x

++

y

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

© 著作权归作者所有

共有 人打赏支持
-愚公移山-
粉丝 0
博文 5
码字总数 24316
作品 0
郑州
前端工程师
kinegratii/Lexer

Lexer #概述 一个用Java Swing编写的C语言词法分析器的Demo项目。 词法分析是编译过程的第一个阶段,是编译的基础。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的...

kinegratii
2014/09/26
0
0
angularjs源码笔记(5.1)--parse

简介 ng提供一个 $parse 服务用于解析与scope值相关的字符串表达式,如: 可以将字符串表达式中的变量映射到scope的变量上执行运算。 $parse 的功能就是编译器,将传入的字符串表达式通过词法...

alexqdjay
2016/08/22
42
0
C++模板”>>”编译问题与词法消歧设计

原文出处:文艺复兴记,2013-10-09 在编译理论中,通常将编译过程抽象为5个主要阶段:词法分析(Lexical Analysis),语法分析(Parsing),语义分析(Semantic Analysis),优化(Optimization),代...

文艺复兴记,2013-10-09
2017/01/06
0
0
Javac编译原理:Item(1)——基本介绍

首先,必须明确Java语言规范和Java虚拟机规范不是一回事。 Java语言规范描述了Java语言有哪些词法和语法,而Java虚拟机也有Java虚拟机规范,它们都有自己的词法和语法解析规则,而且解析规则...

_Roger_
2016/02/16
135
0
Lua2.4 词法分析 lex.c

先看一下在打开文件里用到的一个函数 lua_setinput void lua_setinput (Input fn){ current = ' '; input = fn; if (yytext == NULL) { textsize = MINBUFF; yytext = newvector(textsize, c......

晓寒
2014/10/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【挑战剑指offer】系列03:逆序打印单链表

本系列的算法原题来自于“牛客网-剑指offer”,写这个板块,不仅仅是解决算法问题本身,更是手动提高难度、自行变式,思考更多的解决方案,以带给自己一些启发。 1. 【逆序打印单链表】原始题...

LinkedBear
12分钟前
1
0
Linux内存布局

今天这篇文章主要是我之前看Linux内核相关知识和博客Gustavo Duarte中。我主要是看了这篇博客,并且结合之前的知识,对内存管理的的理解又上升了一个档次。所以想通过这篇文章总结下。 我们先...

linuxprobe16
31分钟前
1
0
day94-20180921-英语流利阅读-待学习

记录死亡还是消费死者?自杀报道的媒体偏见 雪梨 2018-09-21 1.今日导读 自杀事件报道一直是新闻报道的重要部分,具有骇人听闻、吸引眼球的特点。可是在报道这些事件的时候,除了客观陈述事实...

飞鱼说编程
37分钟前
3
0
如何通过 J2Cache 实现分布式 session 存储

做 Java Web 开发的人多数都会需要使用到 session (会话),我们使用 session 来保存一些需要在两个不同的请求之间共享数据。一般 Java 的 Web 容器像 Tomcat、Resin、Jetty 等等,它们会在...

红薯
今天
3
0
C++ std::thread

C++11提供了std::thread类来表示一个多线程对象。 1,首先介绍一下std::this_thread命名空间: (1)std::this_thread::get_id():返回当前线程id (2)std::this_thread::yield():用户接口...

yepanl
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部