ArkTs运算符和表达式

88 阅读6分钟

二、运算符和表达式

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语句的执行流程如下:

  1. 执行init表达式(如有)。此表达式通常初始化一个或多个循环计数器。
  2. 计算condition。如果它为真值(转换后为true的值),则执行循环主体的语句。如果它为假值(转换后为false的值),则for循环终止。
  3. 执行循环主体的语句。
  4. 如果有update表达式,则执行该表达式。
  5. 返回步骤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}'`);
    }
  }
}