TypeScript全栈开发
上QQ阅读APP看书,第一时间看更新

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程序、某个类还是某个局部代码块,后面将详细介绍代码块的知识。

通常来说,在使用函数或类等声明语句时,都必须使用代码块,并将函数或类的所有相关代码放置其中。当使用流程控制语句时,只需在执行多条语句的情况下使用代码块,但推荐都使用代码块,以提升代码的可读性。