2.1 语法结构
我们先看一段简单的代码,通过该案例了解TypeScript的语法结构。
let testScore:number = 100;
// 判断分数是否达到通过标准
if (testScore >= 60){
console.log("考试通过!");
}
对于已经掌握一门编程语言的读者来说,这段代码十分简单。接下来,我们拆分这段代码的各个元素,讲解不同的组成部分。图2-1展示了示例代码的组成部分。
图2-1 示例代码的组成部分
2.1.1 声明变量
本例使用声明符let来声明变量。以下代码用于声明一个名为testScore、类型为数值(number)的变量,并将数值20赋给它。
let testScore:number = 20;
TypeScript使用let语句声明变量,语法如下。
let 变量名称:数据类型=初始值;
let是在ECMAScript 6标准中新增的变量声明语句。在TypeScript中,let的使用方式与ECMAScript 6标准中的完全相同。在本书中推荐使用let来声明变量,不推荐使用落后的var来声明变量。var声明可能会导致各种意想不到的问题,感兴趣的读者可以自行在网上搜索这些问题。
2.1.2 标识符名称
在本例中,变量的名称为testScore。
变量是标识符的一种,在TypeScript中,标识符指变量、函数、参数、类、属性等的名字。标识符的命名必须遵循两条规则。
首先,标识符的名称可以由字母、下画线“_”、$符号或数字组成,但首个字符不能是数字。
以下是符合规则的命名。
a
_bc
$$de
fg123
以下是不符合规则的命名。
1a
,we.?
其次,标识符的名称不能是TypeScript本身已经占用的名称(示例代码中的let、number、if等都是已经被TypeScript占用的名称)。
同时还需注意,TypeScript中的一切名称都区分大小写。例如,testScore和TestScore分别表示两个不同的变量。同样地,let是TypeScript中的关键字,无法用它来作为变量或函数的名称,但LET可以。
2.1.3 数据类型
在本例中,变量的数据类型是数值(number)。
与JavaScript不同,TypeScript拥有完善的类型机制来处理相应的数据。在TypeScript中,基本类型包括原始类型(本例中的数值类型属于原始类型之一)和对象类型,进阶类型包括联合类型、交叉类型和泛型等,这些类型将在后面详细介绍。
TypeScript在声明变量时就可以指定数据类型,这也是TypeScript的核心优势之一。TypeScript编译器能基于数据类型进行静态检查,提前发现代码中的问题。
在赋值表达式中,数据类型并不是必需的,TypeScript会根据实际的初始赋值自动推导出变量的数据类型,并将该类型作为操作和检查的依据,示例代码如下。
let a = 1; //实际等同于let a:number = 1
此时,变量a的值为字符串值,示例代码如下。
a = "hello";
即使没有明确指出变量a的类型,TypeScript也能推导出它是数值类型,如果赋给它其他类型的值,问题窗口中将提示错误消息,如图2-2所示。
图2-2 错误消息
虽然数据类型可以省略,但为了保持代码的可读性,建议在任何时候都保留数据类型的定义。
2.1.4 运算符
使用运算符可将一个或多个值连接起来,形成表达式并进行计算,得到一个结果值。
在本例中,使用了两个运算符。
● 赋值运算符“=”,表示将运算符“=”右边的值赋给左边的变量。
● 比较运算符“>=”,表示判断运算符左侧的值是否大于或等于右侧的值,得出比较结果——是(true)或否(false)。
在TypeScript中,常用的运算符包括赋值运算符、算术运算符(加减乘除等计算)、比较运算符(比大小)、逻辑运算符(判断与、或者、非等逻辑)和条件运算符(根据不同情况得出不同结果)等。
大多数运算符(如“+”和“−”等)是用符号表示的。少部分运算符(如is、as和typeof等)是由关键字表示的。
后面会详细介绍各种运算符。
2.1.5 字面量
在前面的示例中,字面量为数字100、60和字符串“考试通过!”
字面量即代码中直接使用的明文数据值,例如,以下数据值都是字面量。
123 //整数
12.3 //小数
"hello" //字符串
true //布尔值
null //空{a:1,b:2} //对象
[1,2,3,4] //数组
2.1.6 分号与断句
TypeScript使用分号“;”作为一句话的结尾,将这句话与其他语句分隔开。在本例中,使用分号作为赋值语句的结尾。
let testScore:number = 100;
分号并不是必需的,如果每条语句都不在同一行上,也可以省略句末的分号,示例代码如下。
let testScore:number = 100
如果多条语句写到同一行上,则必须以分号结尾,分隔多条语句,示例代码如下。
let a:number=10; let b:number=20
如果一条语句写到多行上,并且语句包含运算符,则情况又将不同。由于运算符会连接其左右的值,因此即使分开写到多行上,也会被解析成一行,示例代码如下。
let a:number =
1
+
2
以上代码等同于以下代码。
let a:number = 1 + 2;
除非遇到特殊情况,否则所有代码都建议使用分号分隔,并且一行只写一条语句,以提升代码的可读性和整洁性。
2.1.7 注释
在本例中,注释为以下语句。
// 判断分数是否达到通过标准
注释中的句子将会忽略,不会执行。
注释通常用于给代码添加说明,在TypeScript中,注释可分为单行注释和多行注释。
单行注释以两条斜杠开头,注释文字需要和斜杠保持在同一行中,示例代码如下。
// 单行注释
多行注释以一条斜杠和一个星号“/*”开头,以一个星号和一条斜杠“*/”结尾,注释文字放在注释开始符与注释结束符之间,示例代码如下。
/*多
行
注
释
*/
2.1.8 表达式
表达式由两部分——运算符及其所连接的数据组成。每一个表达式都会产生一个结果值。
在本例中,表达式为testScore >= 60。使用比较运算符“>=”连接其左右两侧的数据,形成表达式,该表达式将产生一个布尔类型的值。当testScore的值大于或等于60时,返回true;否则,返回false。
表达式产生的值可以赋给其他变量,或用于流程语句的判断。
2.1.9 流程控制
通过流程控制语句,决定接下来的代码是否执行或怎样执行,改变代码的执行顺序。
默认情况下,所有的代码都是按照从上到下、从左到右的顺序依次执行的。图2-3所示为默认执行流程。
图2-3 默认执行流程
使用两种语句——选择语句或循环语句改变原有的执行顺序。
选择语句根据条件判断接下来该执行哪些代码,图2-4所示为选择流程。常见的选择语句有if、if…else、if…else if及switch等。
图2-4 选择流程
在本例中,使用选择语句来实现流程控制。
if (testScore >= 60)
如果变量testScore的值大于或等于60,则执行if后的语句;否则;不执行。
循环语句根据条件判断是否反复执行某一段代码。图2-5所示为循环流程。常见的循环语句有for、while、do…while等。
图2-5 循环流程
后面将一一介绍这些流程控制语句。
2.1.10 代码块
本例中的代码块如下,在代码块中有一行语句,它表示在命令行或控制台中输出“考试通过!”。
{
console.log("考试通过!");
}
在TypeScript中,以左花括号“{”开头,以右花括号“}”结尾,形成代码块,将多条语句组合到一个代码块中,将其视作一个整体来组织、管理和运行,示例代码如下。
if (a > 20){
let b:number = 30;
c = a + b;
console.log(c);
}
代码块将决定变量的作用域,决定其使用范围究竟是整个TypeScript程序、某个类还是某个局部代码块,后面将详细介绍代码块的知识。
通常来说,在使用函数或类等声明语句时,都必须使用代码块,并将函数或类的所有相关代码放置其中。当使用流程控制语句时,只需在执行多条语句的情况下使用代码块,但推荐都使用代码块,以提升代码的可读性。