二、运算符和表达式
1. 运算符
1.1 赋值运算符
赋值运算符=,使用方式如x=y。
复合赋值运算符将赋值与运算符组合在一起,例如:a += b 等价于 a = a + b,
其中的 += 即为复合赋值运算符
复合赋值运算符包括:+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、|=、^=。
赋值运算符用于将右边的值赋给左边的变量。
- =:赋值
- +=:加赋值
- -=:减赋值
- *=:乘赋值
- /=:除赋值
- %=:取余赋值
1.2 比较运算符
| 运算符 | 说明 |
|---|---|
| === | 如果两个操作数严格相等(对于不同类型的操作数认为是不相等的,如string和number),则返回true。 |
| !== | 如果两个操作数严格不相等(对于不同类型的操作数认为是不相等的,如string和number),则返回true。 |
| == | 如果两个操作数相等,则返回true。 |
| != | 如果两个操作数不相等,则返回true。 |
| 如果左操作数大于右操作数,则返回true。 | |
| >= | 如果左操作数大于或等于右操作数,则返回true。 |
| < | 如果左操作数小于右操作数,则返回true。 |
| <= | 如果左操作数小于或等于右操作数,则返回true。 |
let a:Object=1;
let b:Object='1';
// == 只比较值相等
console.info(a == b); // true
// === 比较值和类型都相等
console.info(a === b); // false
1.3 算术运算符
一元运算符包括:-、+、--、++。
二元运算符列举如下:
| 运算符 | 说明 |
|---|---|
| + | 加法 |
| - | 减法 |
| * | 乘法 |
| / | 除法 |
| % | 除法后余数 |
1.4 位运算符
| 运算符 | 说明 |
|---|---|
| a & b | 按位与:如果两个操作数的对应位都为1,则将这个位设置为1,否则设置为0。 |
| a | b | 按位或:如果两个操作数的相应位中至少有一个为1,则将这个位设置为1,否则设置为0。 |
| a ^ b | 按位异或:如果两个操作数的对应位不同,则将这个位设置为1,否则设置为0。 |
| ~ a | 按位非:反转操作数的位。 |
| a << b | 左移:将a的二进制表示向左移b位。 |
| a >> b | 算术右移:将a的二进制表示向右移b位,带符号扩展。 |
| a >>> b | 逻辑右移:将a的二进制表示向右移b位,左边补0。 |
1.5 逻辑运算符
| 运算符 | 说明 |
|---|---|
| a && b | 逻辑与 |
| a || b | 逻辑或 |
| ! a | 逻辑非 |
1.6 条件(三元)运算符
用于根据布尔表达式的结果返回两个值中的一个
condition ? value1 : value2
1.7 类型运算符
类型运算符用于进行类型检查和类型转换
- typeof : 获取变量类型
- instanceof: 判断对象是否为某个类的实例
- as: 类型断言
1.8 空值合并运算符
空值合并二元运算符??用于检查左侧表达式的求值是否等于null或者undefined。如果是,则表达式的结果为右侧表达式;否则,结果为左侧表达式。
换句话说,a ?? b等价于三元运算符(a != null && a != undefined) ? a : b
class Person {
// ...
nick: string | null = null
getNick(): string {
return this.nick ?? '';
}
}
可选连
this.spouse?.nick;
class Person {
nick: string | null = null
spouse?: Person
setSpouse(spouse: Person): void {
this.spouse = spouse;
}
getSpouseNick(): string | null | undefined {
return this.spouse?.nick;
}
constructor(nick: string) {
this.nick = nick;
this.spouse = undefined;
}
}
2. 表达式
2.1 If语句
- if语句用于需要根据逻辑条件执行不同语句的场景。当逻辑条件为真时,执行对应的一组语句,否则执行另一组语句(如果有的话)
- else部分也可能包含if语句。
if (condition1) {
// 语句1
} else if (condition2) {
// 语句2
} else {
// else语句
}
条件表达式可以是任何类型,非boolean类型会进行隐式类型转换:
let s1 = 'Hello';
if (s1) {
console.info(s1); // 打印“Hello”
}
let s2 = 'World';
if (s2.length != 0) {
console.info(s2); // 打印“World”
}
2.2 Switch语句
使用switch语句执行与switch表达式值匹配的代码块
switch (expression) {
case label1: // 如果label1匹配,则执行
// ...
// 语句1
// ...
break; // 可省略
case label2:
case label3: // 如果label2或label3匹配,则执行
// ...
// 语句23
// ...
break; // 可省略
default:
// 默认语句
}
如果switch表达式的值等于某个label的值,则执行相应的语句。
如果没有任何一个label值与表达式值相匹配,并且switch具有default子句,那么程序会执行default子句对应的代码块。
break语句(可选的)允许跳出switch语句并继续执行switch语句之后的语句。
如果没有break语句,则执行switch中的下一个label对应的代码块。
2.3 For语句
2.3.1 for语句
for语句会被重复执行,直到循环退出语句值为false。
for ([init]; [condition]; [update]) {
statements
}
for语句的执行流程如下:
- 执行init表达式(如有)。此表达式通常初始化一个或多个循环计数器。
- 计算condition。如果它为真值(转换后为true的值),则执行循环主体的语句。如果它为假值(转换后为false的值),则for循环终止。
- 执行循环主体的语句。
- 如果有update表达式,则执行该表达式。
- 返回步骤2。
2.3.2 For-of
使用for-of语句可遍历数组、Set、Map、字符串等可迭代的类型
for (forVar of IterableExpression) {
// process forVar
}
2.3.3 For-in
for...in 循环用于遍历对象的属性或数组的索引。它会依次获取对象或数组中的每一个键或索引
for (let key in object) {
// 对象的属性或数组的索引
}
let person = { name: "Alice", age: 30, city: "New York" };
for (let key in person) {
console.log(key, person[key]); // 打印键和值
}
注意: for...in 循环通常用于遍历对象的属性,而不是数组的值。如果需要遍历数组的值,推荐
for...of
2.4 Do-while语句
do...while 循环与while循环体执类似,不同点在于do...while 循环会至少执行一次,因为条件是循环体执行后的判断
do {
// 循环体
} while (condition);
let count = 0;
do {
console.log(count);
count++; // 更新计数器
} while (count < 5)
2.5 Break语句
使用break语句可以终止循环语句或switch。
let x = 0;
while (true) {
x++;
if (x > 5) {
break;
}
}
如果break语句后带有标识符,则将控制流转移到该标识符所包含的语句块之外。
let x = 1;
label: while (true) {
switch (x) {
case 1:
// statements
break label; // 中断while语句
}
}
2.6 Continue语句
continue语句会停止当前循环迭代的执行,并将控制传递给下一个迭代
let sum = 0;
for (let x = 0; x < 100; x++) {
if (x % 2 == 0) {
continue;
}
sum += x;
}
2.7 Throw和Try语句
2.7.1 throw语句
用于抛出异常或错误
throw new Error('this error')
2.7.2 try语句
用于捕获和处理异常或错误
try {
// 可能发生异常的语句块
} catch (e) {
// 异常处理
}
下面的示例中throw和try语句用于处理除数为0的错误
class ZeroDivisor extends Error {}
function divide (a: number, b: number): number{
if (b == 0) throw new ZeroDivisor();
return a / b;
}
function process (a: number, b: number) {
try {
let res = divide(a, b);
console.info('result: ' + res);
} catch (x) {
console.error('some error');
}
}
支持finally语句
function processData(s: string) {
let error: Error | null = null;
try {
console.info('Data processed: ' + s);
// ...
// 可能发生异常的语句
// ...
} catch (e) {
error = e as Error;
// ...
// 异常处理
// ...
} finally {
// 无论是否发生异常都会执行的代码
if (error != null) {
console.error(`Error caught: input='${s}', message='${error.message}'`);
}
}
}