第2章 ArkTS(上)

学习目标

熟悉ArkTS的概念,能够说出什么是ArkTS,以及ArkTS与JavaScript、TypeScript ​ 的关系

掌握调试输出,能够使用console.log()语句输出信息

掌握注释的使用方法,能够合理运用单行注释、多行注释增强代码的可读性

掌握变量、常量和数据类型,能够使用变量、常量和数据类型存储数据

掌握运算符,能够灵活运用运算符完成运算

掌握选择结构语句,能够根据实际需求选择合适的选择结构语句

掌握循环语句,能够根据实际需求选择合适的循环语句

掌握跳转语句,能够灵活运用continue语句或break语句实现程序中的流程跳转

掌握数组和枚举,能够使用数组和枚举存储数据

熟悉函数的概念,能够阐述函数的作用

掌握自定义函数,能够根据实际需求在程序中定义并调用函数

掌握如何将函数作为值使用,能够将函数作为变量值、参数值、返回值或数组元素 ​ 值来使用

掌握箭头函数,能够定义和调用箭头函数

掌握常用的内置函数,能够使用内置函数完成功能开发

熟悉变量的作用域和闭包,能够在开发中正确使用变量的作用域和闭包

ArkTS是鸿蒙应用开发的主力语言。ArkTS围绕鸿蒙应用开发,在TypeScript的生态基础上做了进一步扩展,既保持了TypeScript的基本风格,又通过规范定义强化了开发期静态检查和分析,提升了程序执行稳定性和性能。本章将对ArkTS基础语法进行详细讲解。

2.1 初识ArkTS

ArkTS并不是一门全新的语言。由于JavaScript应用广泛,TypeScript又使JavaScript更加严谨,华为选择在TypeScript的基础上开发ArkTS语言,从而使已经具备JavaScript或TypeScript基础的开发者可以快速上手鸿蒙应用的开发。

JavaScript

JavaScript是Web前端开发中的一门编程语言,最初主要用于开发交互式的网页,实现网页中的各种交互效果,例如,轮播图、选项卡、表单验证等。

随着技术的发展,JavaScript的应用领域变得更加广泛,它还可以用来开发服务器应用、桌面应用和移动应用。

JavaScript语言的标准化由Ecma国际(Ecma International)制定。Ecma国际是一个国际性会员制的信息和电信标准组织,该组织发布了ECMA-262标准文件,规定了浏览器脚本语言的标准,并将这种语言称为ECMAScript。JavaScript是对ECMAScript的实现和扩展。

目前,ECMAScript还在持续更新,比较有代表性的版本是2015年发布的ECMAScript 6,随后几乎每一年都有新版本的发布,例如,2024年6月26日发布的ECMAScript 2024。

  1. TypeScript

TypeScript是微软(Microsoft)公司推出的一门开源的编程语言,它是JavaScript的超集,意味着TypeScript包含JavaScript的所有特性,并在JavaScript的基础上新增了一些新特性,例如静态类型检查、更严格的语法规则、接口、泛型等。

使用TypeScript中的静态类型,开发者可在编码阶段发现并修复潜在的错误,减少代码在运行时出现错误的可能性。同时,TypeScript还支持ECMAScript标准,使用TypeScript编写的代码可以编译成JavaScript代码,从而在JavaScript的环境中运行。

TypeScript提供了更好的开发工具和更严格的代码检查,它广泛应用于大型Web应用程序和框架中,以提高大型应用程序的可维护性和可读性。

  1. ArkTS

ArkTS是华为推出的一门为构建高性能应用而设计的编程语言。由于许多编程语言在设计之初没有考虑到移动设备,导致应用运行缓慢、低效、功耗大,所以针对移动环境的编程语言优化需求越来越大。ArkTS就是专为解决这些问题而设计的,它聚焦于提高运行效率。

ArkTS通过保持TypeScript的大部分语法,为现有的TypeScript开发者实现无缝过渡,让移动开发者能快速上手。

ArkTS的一大特性是它专注于低运行时开销。ArkTS对TypeScript的动态类型特性施加了更严格的限制,以减少运行时开销,提高运行效率。通过取消动态类型特性,ArkTS代码能更有效地在运行前被编译和优化,从而实现更快的应用启动和更低的功耗。

2.2 调试输出和注释

2.2.1 调试输出

在实际开发中,经常需要输出一些信息,从而方便调试程序。

在ArkTS中,使用console.log()语句可以进行调试输出,输出结果可以在DevEco Studio底部的"日志"面板中查看。

console.log()语句的语法格式如下。

复制代码
console.log(参数1, 参数2, …);

小括号中的参数表示要输出的内容,可以传入1个或多个参数,多个参数使用英文逗号分隔,第1个参数必须是字符串,其余参数如果是其他类型数据则会被自动转为字符串。

"..."用于在文档中说明在参数2的后面还可以写更多参数,实际编写代码时不用写"..."。

语句末尾的分号";"表示语句分隔符,在它后面可以写下一条语句。通过换行的方式可以省略语句分隔符。

下面演示如何在项目中进行调试输出。

2.2.2 注释

注释用于对代码进行解释和说明,其目的是让代码阅读者能够更加轻松地了解代码的设计逻辑、用途等。

在实际开发中,为了提高代码的可读性、方便代码的维护和升级,可以在编写代码时添加注释。注释在程序解析时会被忽略。

  1. 单行注释 单行注释以"//"开始,到该行结束为止,示例代码如下。
TypeScript 复制代码
console.log('你好');   // 调试输出
复制代码
  1. 多行注释 多行注释以"/"开始,以"/"结束,示例代码如下。
TypeScript 复制代码
/*
调试输出
*/
console.log('你好');
复制代码

2.3 变量、常量和数据类型

2.3.1 变量

变量是指程序在内存中申请的一块用来存放数据的空间,用于存储程序运行过程中产生的临时数据。例如,将两个数字相乘的结果保存到变量中,以便在后面的计算中使用。

在使用变量时,需要先声明变量。声明变量后,就可以为变量赋值,从而完成数据的存储。

声明变量的语法格式如下。

复制代码
let 变量名: 类型;
​

let是声明变量的关键字。 变量名是指变量的名称。 类型通常会设置为数据类型、类或接口等。例如,字符串'a'对应的数据类型是string,数字1对应的数据类型是number。

关于数据类型、类和接口会在后面进行讲解。

ArkTS允许一个变量有多种类型,将"类型"写成"类型1 | 类型2 | ..."的形式即可。例如,"string | number"表示变量的值可以是字符串或数字。

但ArkTS不支持TypeScript中的any类型。any类型表示任意类型。为了提高代码的严谨性和运行效率,ArkTS禁用了any类型。

变量的命名规则如下。

① 不能以数字开头,且不能包含+、-等运算符,如01user、user-02是非法的变量名。 ② 严格区分大小写,如apple和Apple是两个不同的变量名。 ③ 不能使用ArkTS中的关键字命名。关键字是ArkTS中被事先定义并赋予特殊含义的单词,例如let、if、while就是ArkTS中的关键字。

为了提高代码的可读性,在对变量命名时应遵循以下建议。

① 使用字母、数字、下划线或美元符号()命名,如score、set_name、a、user01。 ② 尽量做到"见其名知其义",如age表示年龄、num表示数字等。 ③ 用下划线分隔多个单词,如show_message;或采用驼峰命名法,即变量的第1个单词首字母小写,后面的单词首字母大写,如leftHand、myFirstName等。

声明变量后,为变量赋值的语法格式如下。

复制代码
变量名 = 值;

声明变量与为变量赋值的代码可以写在同一行,这个过程又称为定义变量或初始化变量,语法格式如下。

复制代码
let 变量名: 类型 = 值;

在定义变量时,如果通过"值"可以自动推断出变量的类型,则变量名后面的": 类型"可以省略。

当需要声明多个变量时,可以写多行声明变量的代码。除了这种方式以外,还可以在一行代码中同时声明多个变量,多个变量之间使用英文逗号分隔,语法格式如下。

复制代码
let 变量名1: 类型, 变量名2: 类型, …;

在一行代码中声明多个变量并为多个变量赋值,语法格式如下。

复制代码
let 变量名1: 类型 = 值1, 变量名2: 类型 = 值2;

下面通过代码演示变量的使用方法。

TypeScript 复制代码
// 声明变量student01并赋值为'小明',设置类型
let student01: string = '小明';
// 声明变量student02并赋值为'小智',省略类型
let student02 = '小智';

使用console.log()输出变量student01和student02的值,示例代码如下。

TypeScript 复制代码
console.log(student01);     // 输出结果:小明
console.log(student02);     // 输出结果:小智

2.3.2 常量

常量是一种在程序运行过程中始终保持不变的数据,例如数学中的圆周率在程序中就可以保存为一个常量。在ArkTS中,常量分为字面量和使用const关键字声明的常量。

字面量

字面量用于表达源码中的固定值。字面量在程序中一旦被定义,其值就不会改变,所以可以将字面量称为常量。

ArkTS中常见的字面量如下。

① 数字字面量:如1、2、3。 ② 字符串字面量:如'用户名'、"密码"。 ③ 布尔字面量:如true、false。 ④ 数组字面量:如1, 2, 3。 ⑤ 对象字面量:如{ username: '小智', password: '123456' }。

  1. 使用const关键字声明的常量

使用const关键字声明的常量类似于变量,但是它的值不能发生改变。在为常量命名时,为了方便将它与变量区分,习惯上将常量的名称设置为全大写。

JavaScript设计之初并没有const关键字,const关键字是随着JavaScript的发展在后期加入的,并沿用到ArkTS中。const关键字在声明变量的语法基础上增加了一种使变量的值保持不变的语法约束,因此可以将使用const关键字声明的变量称为常量。基于这样的历史原因,在不需要区分变量和常量的语境下,变量一词也笼统地包含使用const关键字声明的常量,这种常量可以理解为"不可变的变量"。

**注意:**当使用const关键字声明的常量的值是数组、对象时,数组的元素、对象的成员是可以改变的,但是常量本身不能被重新赋值。

下面通过代码演示如何使用const关键字声明常量,并输出常量的值,示例代码如下。

TypeScript 复制代码
const STUDENT: string = '小明';
console.log(STUDENT);       // 输出结果:小明

上述代码声明了一个常量STUDENT并赋值为'小明',使用console.log()输出了常量STUDENT的值。

2.3.3 数据类型

在ArkTS中常用的数据类型有:

  • string(字符串)

  • number(数字)

  • boolean(布尔)

  • null(空)

  • void(空)

  • undefined(未定义)

  • object(对象)

string

string表示字符串,需要使用单引号(')、双引号(")或反引号(`)标注。

字符串中的字符可以是0个或多个。其中,使用反引号(`)标注的字符串称为模板字符串,在模板字符串中通过"${变量名}"的方式可以使用变量的值。

下面通过代码演示string数据类型的使用方法。声明3个变量,分别给这3个变量赋值为使用单引号、双引号和反引号标注的字符串,并进行调试输出,示例代码如下。

TypeScript 复制代码
let stu1: string = '小明';
let stu2: string = "小智";
let introduce: string = `${stu1}和${stu2}是好朋友`;
console.log(stu1);      // 输出结果:小明
console.log(stu2);      // 输出结果:小智
console.log(introduce);     // 输出结果:小明和小智是好朋友

在字符串中可以使用转义字符来表示一些特殊符号。转义字符以"\"开始,常用的转义字符如下表所示。

转义字符 含义
' 单引号"'"
'' 双引号"""
` 反引号"`"
\n 换行符
\t 水平制表符
\f 换页符
\b 退格符
转义字符 含义
\xhh 由两位十六进制数字hh表示的ISO-8859-1字符,如\x61表示"a"
\v 垂直制表符
\r 回车符
\ 反斜线"\"
\0 空字符
\uhhhh 由四位十六进制数字hhhh表示的Unicode字符,如\u597d表示"好"
  1. number number表示数字,分为整数、浮点数(可以理解为小数)和特殊值。在数字前面还可以添加"-"符号表示负数,添加"+"符号表示正数(通常情况下省略"+")。

(1)整数 整数通常使用十进制表示,此外还可以使用二进制、八进制、十六进制来表示。 二进制数以0b开头,八进制数以0o开头,十六进制数以0x开头,其中,b、o、x不区分大小写。

下面通过代码演示number数据类型中整数的使用方法。声明4个变量,分别给这4个变量赋值为二进制、八进制、十进制、十六进制的整数,示例代码如下。

TypeScript 复制代码
let bin: number = 0b11010;      // 二进制表示的26
let oct: number = 0o32;         // 八进制表示的26
let dec: number = 26;       // 十进制表示的26
let hex: number = 0x1a;         // 十六进制表示的26

(2)浮点数

浮点数类似数学中小数的写法,如1.10。

整数和浮点数还可以使用科学记数法表示。

科学记数法是指将数字表示成一个数与10的n次幂相乘的形式,在程序中使用E或e后面跟一个数字的方式表示10的n次幂,如2.15E3表示2.15103。

下面通过代码演示number数据类型中浮点数和科学记数法的使用方法,示例代码如下。

TypeScript 复制代码
// 浮点数
let fNum01: number = -3.12;
let fNum02: number = 3.12;
// 科学记数法
let fNum03: number = 3.14E5;
let fNum04: number = 7.35E-5;

(3)特殊值

number类型有3个特殊值,分别是Infinity(无穷大)、-Infinity(无穷小)和NaN(Not a Number,非数字)。

当计算结果超出了最大可表示的数字时,会返回Infinity。 当计算结果超出了最小可表示的数字时,会返回-Infinity。 如果进行了非法的运算操作,则运行结果为NaN。

  1. Boolean

boolean表示布尔,该类型只有true(真)和false(假)两个值。

boolean数据类型通常用于表示程序中的逻辑判断结果。

true表示事件成功或条件成立的情况, false表示事件失败或条件不成立的情况。

例如,判断数字3是否大于数字2,其结果用boolean数据类型表示为true。

下面通过代码演示boolean数据类型的使用方法。声明两个变量,分别赋值为true和false,示例代码如下。

TypeScript 复制代码
let result01: boolean = true;
let result02: Boolean = false;
  1. null

null表示空,通常用于表示变量未指向任何对象,该类型只有一个null值。

下面通过代码演示null数据类型的使用方法。声明一个变量,将其赋值为null,示例代码如下。

TypeScript 复制代码
let empty: null = null;
  1. void

void表示空,通常用于表示函数没有返回值,该类型只有一个void值。关于函数的相关内容会在后面进行讲解。

下面通过代码演示void数据类型的使用方法。声明一个变量,其类型为void,示例代码如下。

TypeScript 复制代码
let data: void;
  1. undefined

undefined表示未定义。当声明的变量还未被赋值时,该变量的值为undefined。

下面通过代码演示undefined数据类型的使用方法。声明两个变量,将第1个变量赋值为undefined,第2个变量不进行赋值,示例代码如下。

TypeScript 复制代码
let num01: undefined = undefined;
let num02: undefined;
  1. object

object表示对象,它是一种引用数据类型,而其他数据类型则属于基本数据类型。

引用数据类型的特点是当它被赋值给变量时,变量保存的是对象的引用,同一个对象可以被多个变量引用,从而节省内存空间。

ArkTS中的对象有多种形式,常见的形式如下。

① 字面量对象:通过对象字面量语法"{}"创建的对象,通常用于保存一些数据。 ② 实例:通过类(class)或构造函数创建的对象,这样的对象被称为某个类或构造函数的实例。 ③ 函数:用于对一些代码进行封装,从而方便使用。函数的常见形式有用户自定义函数、内置函数、方法、构造函数等。 ④ 数组:用于保存一批相同数据类型的数据。 ⑤ 枚举:用于预先定义一些值,方便在开发中使用。 ⑥ 内置对象:预先提供的一些对象,方便在开发中使用。 ⑦ 包装对象:对基本数据类型的数据自动装箱产生的对象,用于使一些基本数据类型的数据可以像对象一样使用。

2.4 运算符

2.4.1 算术运算符

算术运算符用于对两个数字或变量进行算术运算,与数学中的加法、减法、乘法、除法运算类似。

运算符 运算 示例 结果
+ 3 + 3 6
- 6 - 3 3
* 3 * 5 15
/ 8 / 2 4
% 取模(取余数) 5 % 7 5
** 幂运算 4 ** 2 16
++ 自增(前置) a = 2; b = ++a; a = 3; b = 3;
自增(后置) a = 2; b = a++; a = 3; b = 2;
-- 自减(前置) a = 2; b = --a; a = 1; b = 1;
自减(后置) a = 2; b = a--; a = 1; b = 2;

自增和自减运算可以快速对变量的值进行递增或递减,自增和自减运算符可以放在变量前也可以放在变量后。

当自增(或自减)运算符放在变量前时,称为前置自增(或前置自减)。 当自增(或自减)运算符放在变量后时,称为后置自增(或后置自减)。

前置和后置的区别在于,前置返回的是计算后的结果,后置返回的是计算前的结果。

下面通过代码演示自增和自减运算,示例代码如下。

TypeScript 复制代码
let a = 2, b = 2, c = 3, d = 3;
// 自增
console.log('++a的值为', ++a);     // 输出结果:++a的值为 3
console.log('a的值为', a);         // 输出结果:a的值为 3
console.log('b++的值为', b++);     // 输出结果:b++的值为 2
console.log('b的值为', b);         // 输出结果:b的值为 3
// 自减
console.log('--c的值为', --c);         // 输出结果:--c的值为 2
console.log('c的值为', c);         // 输出结果:c的值为 2
console.log('d--的值为', d--);     // 输出结果:d--的值为 3
console.log('d的值为', d);         // 输出结果:d的值为 2

在实际应用算术运算符的过程中,还需要注意以下4点。

① 进行四则混合运算时,运算顺序要遵循数学中"先乘除后加减"的原则。例如,运行"let a = 2 + 8 - 3 * 2 / 2;"后,a的值是7。

② 在进行取模运算时,运算结果的正负取决于被模数(%左侧的数)的正负,与模数(%右侧的数)的正负无关。例如,运行"let a = (-8) % 7, b = 8 % (-7);"后,a的值为-1,b的值为1。

③ 在开发中尽量避免使用浮点数进行运算,因为运算结果可能存在偏差。例如,0.1 + 0.2正常的计算结果应该是0.3,但是ArkTS的计算结果却是0.30000000000000004。此时,可以将参与运算的小数转换为整数,计算后再转换为小数。例如,将0.1和 0.2分别乘10,相加后再除以10,即可得到0.3。

④ "+"和"-"在运算符中还可以表示正数或负数。例如,+2.1 + -1.1的计算结果为1。

2.4.2 字符串运算符

当"+"运算符左右两侧的数据至少有一个为string数据类型时,"+"表示字符串运算符,用于实现字符串的拼接。

下面通过代码演示字符串运算符的使用方法。声明两个变量,第1个变量存放用户名"小智",第2个变量存放性别"男",如果需要显示"小智,男",就需要将字符串"小智"",""男"进行拼接,示例代码如下。

TypeScript 复制代码
let username = '小智';
let gender = '男';
console.log(username + ',' + gender);   // 输出结果:小智,男

使用字符串运算符将字符串与数字进行拼接,示例代码如下。

TypeScript 复制代码
console.log('小智,' + 18);            // 输出结果:小智,18

表达式是一组代码的集合,每个表达式的运行结果都有一个值。变量和各种类型的数据都可以用于构成表达式。一个最简单的表达式可以是一个变量或字面量。假设有number类型的变量a和b,下面列举一些常见的表达式。

TypeScript 复制代码
7;          // 表达式"7"
a = 7;      // 将表达式"7"的值赋值给a
b = a = 7;      // 将表达式"a = 7"的值赋值给b
a + 1;      // 将表达式"a"的值与表达式"1"的值相加
a = a + 1;      // 将表达式"a + 1"的值赋值给a
console.log('' + b);    // 将表达式"'' + b"的值作为参数传给console.log()

2.4.3 赋值运算符

赋值运算符用于将运算符右侧的值赋给左侧的变量。

运算符 运算 示例 结果
= 赋值 a = 1, b = 2; a = 1, b = 2;
+= 加并赋值 a = 1, b = 2; a += b; a = 3, b = 2;
字符串拼接并赋值 a = 'abc'; a += 'def'; a = 'abcdef';
-= 减并赋值 a = 4, b = 3; a -= b; a = 1, b = 3;
*= 乘并赋值 a = 4, b = 3; a *= b; a = 12, b = 3;
/= 除并赋值 a = 4, b = 2; a /= b; a = 2, b = 2;
%= 取模并赋值 a = 4, b = 3; a %= b; a =1, b = 3;

赋值运算符用于将运算符右边的值赋给左边的变量。

运算符 运算 示例 结果
**= 幂运算并赋值 a = 4; a ** = 2; a = 16;
<<= 左移位并赋值 a = 9, b = 2; a <<= b; a = 36, b = 2;
>>= 右移位并赋值 a = -9, b = 2; a >>= b; a = -3, b = 2;
>>>= 无符号右移位并赋值 a = -9, b = 2; a >>>= b; a = 1073741821, b = 2;
&= 按位与并赋值 a = 3, b = 9; a &= b; a = 1, b = 9;
^= 按位异或并赋值 a = 3, b = 9; a ^= b; a = 10, b = 9;
|= 按位或并赋值 a = 3, b = 9; a |= b; a = 11, b = 9;

下面以+=、-=、*=、/=、%=、**=为例演示赋值运算符的使用方法,示例代码如下。

TypeScript 复制代码
let num = 5;
num += 3;                       // 相当于num = num + 3
console.log('', num);       // 输出结果:8
num -= 4;                       // 相当于num = num - 4
console.log('', num);       // 输出结果:4
num *= 2;                       // 相当于num = num * 2
console.log('', num);           // 输出结果:8
num /= 2;                       // 相当于num = num / 2
console.log('', num);           // 输出结果:4
num %= 2;                       // 相当于num = num % 2
console.log('', num);           // 输出结果:0
num **= 2;                          // 相当于num = num ** 2
console.log('', num);           // 输出结果:0

2.4.4 比较运算符

比较运算符用于对两个数据进行比较,比较返回的结果是true或false。

运算符 运算 示例 结果
> 大于 3 > 2 true
< 小于 3 < 2 false
>= 大于或等于 3 >= 2 true
<= 小于或等于 3 <= 2 false
== 等于 3 == 3 true
!= 不等于 3 != 3 false
=== 全等 3 === 3 true
!== 不全等 3 !== 3 false

需要说明的是,"=="和"!=" 在JavaScript中比较不同数据类型的数据时会自动将其转换成相同数据类型后再比较,而在ArkTS中比较不同数据类型的数据会报错。"==="和"!==" 在比较时不会进行数据类型的转换。

下面通过代码演示比较运算符的使用方法,示例代码如下。

TypeScript 复制代码
console.log('', 13 > 12);           // 输出结果:true
console.log('', 13 < 12);           // 输出结果:false
console.log('', 13 >= 12);          // 输出结果:true
console.log('', 13 <= 12);          // 输出结果:false
console.log('', 13 == 13);          // 输出结果:true
console.log('', 13 != 13);          // 输出结果:false
console.log('', 13 === 13);         // 输出结果:true
console.log('', 13 !== 13);         // 输出结果:false

2.4.5 逻辑运算符

在开发中,有时需要在多个条件同时成立时才会执行后续的代码,例如,只有用户输入了有效的用户名和密码,才能登录成功。在程序中,如果要实现条件的判断,可以使用逻辑运算符。

运算符 运算 示例 结果
&& a && b 如果a的值为true,则结果为b的值;如果a的值为false,则结果为a的值
|| a || b 如果a的值为true,则结果为a的值;如果a的值为false,则结果为b的值
! !a 如果a为true,则结果为false;如果a为false,则结果为true

逻辑运算符并不是直接判断一个值是否为true或false,而是采用评估的方式进行判断。

所谓评估是源自JavaScript中的一种对待不同数据类型数据的逻辑判断规则,这种规则会将false、0、''、null、undefined、NaN这些值评估为false,将其他值评估为true。ArkTS也沿用了这样的规则。

下面通过代码演示逻辑运算符的使用方法,示例代码如下。

TypeScript 复制代码
// 逻辑"与"
console.log('', 100 && 200);        // 输出结果:200
console.log('', 0 && 123);          // 输出结果:0
console.log('', 3 > 2 && 4 > 3);        // 输出结果:true
console.log('', 2 < 1 && 3 > 1);        // 输出结果:false
// 逻辑"或"
console.log('', 100 || 200);        // 输出结果:100
console.log('', 0 || 123);          // 输出结果:123
console.log('', 3 > 2 || 4 < 3);        // 输出结果:true
console.log('', 2 < 1 || 3 < 1);        // 输出结果:false
// 逻辑"非"
console.log('', !1);            // 输出结果:false
console.log('', !0);            // 输出结果:true

在使用"&&"和"||"运算符时,是按照从左到右的顺序进行求值的,在运算时可能会出现"短路"的情况。"短路"是指如果通过逻辑运算符左边的表达式能够确定最终值,则不计算逻辑运算符右侧表达式的值。

下面通过代码演示逻辑运算符出现"短路"的情况,示例代码如下。

TypeScript 复制代码
let aa = 1;
false && aa++;      // "&&"短路情况
console.log('', aa);    // 输出结果:1
true || aa++;       // "||"短路情况
console.log('', aa);    // 输出结果:1

2.4.6 三元运算符

三元运算符包括"?"和":",用于组成三元表达式。三元表达式用于根据条件表达式的值来决定"?"后面的表达式和":"后面的表达式哪个被运行。 三元表达式的语法格式如下。

复制代码
条件表达式 ? 表达式1 : 表达式2

如果条件表达式为true,则返回表达式1的运行结果。 如果条件表达式为false,则返回表达式2的运行结果。

三元运算符在判断true和false时,会采用评估的方式,即false、0、''、null、undefined、NaN这些值将被评估为false,其他值将被评估为true。

下面通过代码演示三元运算符的使用,示例代码如下。

TypeScript 复制代码
let age = 18;
let status = age >= 18 ? '已成年' : '未成年';
console.log(status);            // 输出结果:已成年

2.4.7 数据类型检测运算符

使用typeof运算符可以对数据的类型进行检测。typeof运算符以字符串形式返回检测结果,语法格式如下。

复制代码
// 第1种语法格式
typeof 需要进行数据类型检测的数据
// 第2种语法格式
typeof(需要进行数据类型检测的数据)

第1种语法格式只能检测单个数据。 第2种语法格式可以对表达式进行检测。

下面通过代码演示如何使用typeof运算符检测数据类型,示例代码如下。

TypeScript 复制代码
console.log(typeof 23);         // 输出结果:number
console.log(typeof '水果');           // 输出结果:string
console.log(typeof false);          // 输出结果:boolean
console.log(typeof []);         // 输出结果:object

2.4.8 运算符的优先级

在ArkTS中,运算符遵循先后的运算顺序,这种顺序称作运算符的优先级。

结合方向 运算符
()
左(new除外) .、\[\]、new(有参数,无结合性)
new(无参数)
++(后置)、--(后置)
! 、~、-(负数)、+(正数)、++(前置)、--(前置)、typeof、delete
**
*、/、%
+、-
<<、>>、>>>
<、<=、>、>=、in、instanceof
结合方向 运算符
==、!=、===、!==
&
^
|
&&
||
?:
=、+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=、|=
,

运算符的优先级由上到下递减,同一单元格中的运算符具有相同的优先级。左结合方向表示同级运算符的运算顺序为从左向右,右结合方向表示同级运算符的运算顺序为从右向左。

运算符中小括号"()"的优先级最高,在进行运算时要首先计算小括号内的表达式。如果表达式中有多个小括号,则最内层小括号的优先级最高。

下面通过代码演示未使用小括号的表达式和使用小括号的表达式的运算顺序,示例代码如下。

TypeScript 复制代码
console.log('', 3 + 4 * 5);               // 输出结果:23
console.log('', (3 + 4) * 5);             // 输出结果:35

当表达式中有多种运算符时,可根据需要为表达式添加小括号,这样可以使代码更清晰,并且可以避免错误的发生。

2.5 流程控制

2.5.1 选择结构

ArkTS提供了选择结构语句(或称为条件判断语句)来实现程序的选择结构。选择结构语句是指根据语句中的条件表达式进行判断,进而运行相对应的代码。

常用的选择结构语句有if语句、if...else语句、if...else if...else语句和switch语句。

if语句

if语句也称为单分支语句、条件语句,具体语法格式如下。

复制代码
if (条件表达式) {
  代码段
}

如果代码段中只有一条语句,则可以省略大括号。

if语句在判断true和false时,会采用评估的方式进行判断。其他选择结构语句也都采用评估的方式进行判断,即false、0、''、null、undefined、NaN这些值将被评估为false,其他值将被评估为true,后续不赘诉。

下面通过代码演示if语句的使用方法,实现只有当年龄大于或等于18周岁时,才输出"已成年",否则不输出任何信息,示例代码如下。

TypeScript 复制代码
let age1 = 23;
if (age1 >= 18) {
  console.log('已成年');       // 当age1 >= 18时输出"已成年"
}
  1. if...else语句

if...else语句也称为双分支语句,具体语法格式如下。

复制代码
if (条件表达式) {
  代码段1
} else {
  代码段2
}

下面通过代码演示if...else语句的使用方法,实现当年龄大于或等于18周岁时,输出"已成年",否则输出"未成年",示例代码如下。

TypeScript 复制代码
let age2 = 17;
if (age2 >= 18) {
  console.log('已成年');       // 当 age2 >= 18时输出"已成年"
} else {
  console.log('未成年');           // 当age2 < 18时输出"未成年"
}
  1. if...else if...else语句 if...else if...else语句也称为多分支语句,是指有多个条件表达式的语句,可针对不同情况进行不同的处理,具体语法格式如下。
复制代码
if (条件表达式1) {
  代码段1
} else if (条件表达式2) {
  代码段2
}
…
else if (条件表达式n) {
  代码段n
} else {
  代码段n+1
}

if...else if...else语句的运行流程如下图所示。

下面通过代码演示if...else if...else语句的使用方法。对学生考试成绩按分数进行等级的划分,90~100分为优秀,80~90(不含)分为良好,70~80 (不含)分为中等,60~70 (不含)分为及格,小于60分为不及格,示例代码如下。

TypeScript 复制代码
let score = 78;
if (score >= 90) {
  console.log('优秀');        // 当score >= 90时输出"优秀"
} else if (score >= 80) {
  console.log('良好');        // 当score >= 80且score < 90时输出"良好"
} else if (score >= 70) {
  console.log('中等');        // 当score >= 70且score < 80时输出"中等"
} else if (score >= 60) {
  console.log('及格');        // 当score >= 60且score < 70时输出"及格"
} else {
  console.log('不及格');       // 当score < 60时输出"不及格"
}
  1. switch语句 switch语句也称为多分支语句,该语句与if...else if...else语句类似,区别是switch语句只能针对某个表达式的值做出判断,从而决定运行哪一段代码。
复制代码
switch (表达式) {
  case 值1:
    代码段1;
    break;
  case 值2:
    代码段2;
    break;
  …
  default:
    代码段n;
}

switch语句的运行流程如下图所示。

下面通过代码演示switch语句的使用方法。判断变量week的值,当week变量的值为1~6时,输出星期一~星期六,当变量week的值为0时,输出星期日;如果没有与变量week的值相等的case值,则输出"输入错误,请重新输入" 。

TypeScript 复制代码
let week = 3;
switch (week) {
  case 0:
    console.log('星期日');
    break;
  case 1:
    console.log('星期一');
    break;
  case 2:
    console.log('星期二');
    break;
  case 3:
    console.log('星期三');
    break;
  case 4:
    console.log('星期四');
    break;
  case 5:
    console.log('星期五');
    break;
  case 6:
    console.log('星期六');
    break;
  default:
    console.log('输入错误,请重新输入');
};

2.5.2 循环结构

循环结构是为了在程序中反复运行某个功能而设置的一种程序结构,它用于实现一段代码的重复运行。

例如,连续输出1~100的整数,如果不使用循环结构,则需要编写100次输出代码才能实现,而使用循环结构,仅使用几行代码就能让程序自动输出。

在循环结构中,由循环体和循环条件组成的语句称为循环语句,一组被重复运行的语句称为循环体,循环体能否重复运行,取决于循环条件。

ArkTS提供了3种循环语句,分别是for语句、while语句、do...while语句。

for语句

在程序开发中,for语句通常用于循环次数已知的情况,其语法格式如下。

复制代码
for (初始化变量; 条件表达式; 操作表达式) {
  循环体
}

① 初始化变量:初始化一个用作计数器的变量,通常使用let关键字声明一个变量并赋初始值。 ② 条件表达式:决定循环是否继续,即循环条件。如果条件表达式的值为true,表示循环继续;如果条件表达式的值为false,表示循环结束。 ③ 操作表达式:通常用于对计数器变量进行更新(递增或递减),是每次循环中最后运行的代码。

for语句在判断true和false时,会采用评估的方式,即false、0、''、null、undefined、NaN这些值将被评估为false,其他值将被评估为true。其他循环结构语句也都采用评估的方式进行判断,后续不赘诉。for语句的运行流程如下图所示。

下面通过代码演示for语句的使用方法。使用for语句实现输出1~100的整数,示例代码如下。

TypeScript 复制代码
for (let i = 1; i <= 100; i++) {
  console.log('', i);         // 输出1~100(每次循环输出一个数字)
}
TypeScript 复制代码
//九九乘法表
for (let i=1;i<10;i++){
  let info:string="";
  for (let j=1;j<=i;j++){
    info+=j+"*"+i+"="+(j*i)+"\t"
  }
  console.log(info)
}
  1. while语句

while语句和for语句可以相互转换,都能够实现循环。在无法确定循环次数的情况下,while语句更适用。while语句的语法结构如下。

复制代码
while (条件表达式) {
  循环体
}

下面使用while语句实现输出1~100的整数,示例代码如下。

TypeScript 复制代码
let i = 1; 
while (i <= 100) {
  console.log('', i);
  i++;
}
  1. do...while语句

do...while语句和while语句类似,其区别在于while语句是先判断条件表达式的值,再根据条件表达式的值决定是否运行循环体,而do...while语句会无条件地运行一次循环体,然后判断条件表达式的值,根据条件表达式的值决定是否继续运行循环体。

do...while语句的语法格式如下。

复制代码
do {
  循环体
} while (条件表达式);

do...while语句先运行循环体,然后判断条件表达式的值。如果条件表达式的值为true,则进入下一次循环,否则结束循环。

下面通过代码演示do...while语句的使用方法。使用do...while语句实现输出1~100的整数,示例代码如下。

TypeScript 复制代码
let j = 1; 
do {
   console.log('', j);
   j++;
 } while (j <= 100)

2.5.3 跳转语句

循环语句运行后,会根据设置好的循环条件停止运行。在循环运行过程中,如果需要跳出本次循环或跳出整个循环,就需要用到跳转语句。

常用的跳转语句有continue语句和break语句。

  1. continue语句 continue语句可以在for语句、while语句和do...while语句的循环体中使用,用于立即跳出本次循环,即跳过continue语句后面的代码,继续下一次循环。

例如,小智在吃桃子,一共有6个桃子,吃到第2个桃子时,小智发现里面有虫子,就扔掉第2个桃子,继续吃剩下的4个桃子。下面通过代码演示小智扔掉第2个桃子,继续吃剩下的4个桃子的过程,示例代码如下。

TypeScript 复制代码
for (let i = 1; i <= 6; i++) { 
  if (i == 2) { 
    continue;                            // 跳出本次循环,直接跳到i++ 
  } 
  console.log(`小智吃完了第${i}个桃子`); 
}
  1. break语句 当在for语句、while语句和do...while语句中使用break语句时,表示立即跳出整个循环,也就是结束循环。

例如,小智在吃桃子,一共有6个桃子,吃到第4个桃子时,小智发现里面有虫子,于是扔掉了有虫子的桃子并且不再吃剩下的桃子。下面通过代码演示小智吃桃子的过程,示例代码如下。

TypeScript 复制代码
for (let i = 1; i <= 6; i++) {
  if (i == 4) {
    break;                         // 跳出整个循环
  }
  console.log(`小智吃完了第${i}个桃子`);
}

break语句还可以用于跳转到指定的标签语句处,实现循环嵌套中的多层跳转。在使用break语句前,需要先为语句添加标签。为语句添加标签的语法格式如下。

复制代码
标签名:
  语句

为语句添加标签后,使用break语句跳转到指定标签的语法格式如下。

复制代码
break 标签名;

注意:标签语句必须在使用之前定义,否则会出现找不到标签的情况。

下面通过代码演示标签语句的使用方法,示例代码如下。

TypeScript 复制代码
outerLoop:
  for (let i = 0; i < 10; i++) {
    for (let j = 0; j < 1; j++) {
      if (i == 5) {
        break outerLoop;
      }
      console.log('i = ' + i + ', j = ' + j);
    }
  }

2.6 数组和枚举

2.6.1 数组

在实际开发中,经常需要保存一批相关联的数据并对其进行处理。例如,保存一个班级中所有学生的语文考试成绩并计算这些成绩的平均分。虽然我们可以通过多个变量分别保存每个学生的语文考试成绩,再将这些变量相加后除以班级人数,求出平均分,但是这种方式非常麻烦和低效。

此时,可以使用数组来保存班级内每个学生的成绩,然后通过对数组的处理求出平均分,这种方式不仅简单,而且开发效率更高。

数组由0个或多个元素组成,数组中的每个元素由索引和值构成,其中,索引也称为下标,用数字表示,默认情况下从0开始依次递增,用于标识元素;值为元素的内容。

假设某个数组包含5个元素,这5个元素的值分别是55、65、75、85、95,该数组中索引和值的关系如下图所示。

数组的基本使用方法

通过数组字面量创建数组的语法格式如下。

复制代码
[值1, 值2, …]

中括号"\[\]"中的值就是数组中的元素,元素之间使用英文逗号分隔,在值2的后面还可以有更多的值。值1的索引为0,值2的索引为1。 当数组中没有元素时,"\[\]"内不写任何内容。

将数组赋值给变量时,变量的类型可以写成"元素类型\[\]"或"Array<元素类型>"的形式,也可以省略类型,ArkTS会自动推断变量类型。

另外,通过"(元素类型1 | 元素类型2 | ...)\[\]"或"Array<元素类型1 | 元素类型2 | ...>"可以表示数组中的元素有多种类型。

下面通过代码演示数组的基本使用方法。声明两个变量,赋值为数组,示例代码如下。

TypeScript 复制代码
let fruits: string[] = ['苹果', '香蕉', '橘子', '草莓'];
let scores: number[] = [98, 97, 100, 65];

将数组赋值给变量后,通过"变量名索引"的方式可以访问数组中的元素,如果元素不存在则访问结果为undefined;也可以对数组中的元素进行添加或修改,示例代码如下。

TypeScript 复制代码
let fruits1: string[] = ['苹果', '香蕉', '橘子'];
// 访问数组中的元素
let index = 1;
console.log(fruits1[0]);        // 输出结果:苹果
console.log(fruits1[index]);        // 输出结果:香蕉
// 添加数组中的元素
fruits1[3] = '草莓';
// 修改数组中的元素
fruits1[2] = '菠萝';
  1. 二维数组

根据维数,数组可以分为一维数组、二维数组等。一维数组中数组元素的值是非数组类型的数据,二维数组是以一维数组作为数组元素的数组。二维数组在实际编程中应用广泛。例如,二维数组可以用于表示二维表格、矩阵等。

在ArkTS中,可以使用"\[\]"嵌套的方式创建二维数组,语法格式如下。

复制代码
[[元素1, 元素2, …], [元素1, 元素2, …], …]

一个二维数组中可以包含0个或多个一维数组,一维数组中的元素非数组。在访问二维数组中的元素时需要使用两个"\[\]"。

下面通过代码演示如何创建与访问二维数组,示例代码如下。

TypeScript 复制代码
// 创建二维数组
let arr: number[][] = [[89, 98, 80], [95, 83, 85]];
// 访问二维数组
console.log('', arr[0][0]);         // 输出结果:89
console.log('', arr[0][1]);         // 输出结果:98
console.log('', arr[0][2]);             // 输出结果:80
console.log('', arr[1][0]);             // 输出结果:95
console.log('', arr[1][1]);         // 输出结果:83
console.log('', arr[1][2]);             // 输出结果:85
console.log('', arr[0]);            // 输出结果:89,98,80
console.log('', arr[1]);                // 输出结果:95,83,85

2.6.2 枚举

在开发中经常需要保存一些预设的值,方便后续使用。

例如,某个页面有3种主题颜色,这3种主题颜色的色值就可以保存为预设的值。使用枚举可以很方便地保存预设的值。

枚举由一组命名值组成,这些命名值又称为枚举常量,用于预先定义一些值。 枚举的语法格式如下。

复制代码
// 语法格式1
enum 枚举名1 { 枚举常量名1, 枚举常量名2, 枚举常量名3 }
// 语法格式2
enum 枚举名2 { 枚举常量名1 = 值1, 枚举常量名2 = 值2, 枚举常量名3 = 值2 }

enum为声明枚举的关键字,建议将枚举名和枚举常量名中的每个单词首字母大写。 枚举常量的数量可以是0个或多个。 在语法格式1中有3个枚举常量,未对枚举常量赋值,它们的值默认为0、1、2。 在语法格式2中也有3个枚举常量,并为它们分别赋值。

定义了枚举后,使用"枚举名.枚举常量名"可以访问枚举常量的值。

下面通过代码演示枚举的使用方法,示例代码如下。

TypeScript 复制代码
enum ColorSet { Red = '#f00', Green = '#0f0', Blue = '#00f' }
console.log(ColorSet.Red);      // 输出结果:#f00

2.7 函数

2.7.1 初识函数

函数是实现某个特定功能的一段代码,也就是将包含一条或多条语句的代码块封装起来,用户在使用时只需关心参数和返回值,就能实现特定的功能。

对开发者来说,使用已经得到充分检验的函数实现某个功能时,可以将精力集中在所需实现的具体功能上,而无须深入研究函数内部的代码,这并不影响函数的正常使用。函数的优势在于可以提高代码的可复用性,降低代码的维护难度。

在ArkTS中,函数分为内置函数和自定义函数。

内置函数是指可以直接调用的函数。 自定义函数是指用户自定义的实现某个特定功能的函数。

自定义函数在使用之前首先要定义,定义后才能调用,在要实现特定功能时可以调用相对应的函数。

2.7.2 自定义函数

在开发一个功能复杂的模块时,可能需要多次用到相同的代码,这时可以使用自定义函数将相同的代码封装起来,在需要使用时直接调用该函数。

在ArkTS中可以根据实际需求定义函数,定义函数的语法格式如下。

复制代码
function 函数名(参数1: 类型, 参数2: 类型, …): 返回值类型 {
  函数体
}

定义函数的语法格式的具体介绍如下。 ① function:定义函数的关键字。 ② 函数名:一般由字母、数字、下划线和$符号组成。需要注意的是,函数名不能以数字开头,且不能是关键字。 ③ 参数:是外界传递给函数的值,它的数量可以是0个或多个,多个参数之间使用英文逗号","分隔。如果参数是可选的,可以用"参数?: 类型"或"参数: 类型 = 默认值"的方式表示,后者用于在省略参数的情况下为参数设置默认值,如果不设置默认值,则默认值为undefined。可选参数必须放在所有非可选参数的后面。 ④ 函数体:由函数内所有代码组成的整体,专门用于实现特定功能。若需要返回值,可以在函数体中使用return关键字返回,例如"return 'a';"表示返回值为'a'。如果一个函数没有返回值,则调用函数后获取到的返回结果为undefined。 ⑤ ": 返回值类型":用于设置返回值的类型,可以省略,若省略表示自动推断返回值类型。如果没有返回值,可以用": void"来表示。

定义完函数后,如果想要在程序中调用函数,只需要通过"函数名()"的方式调用即可,小括号中可以传入参数。调用函数的语法格式如下。

复制代码
函数名(参数1, 参数2, …);

参数表示传递给函数的一些数据。调用函数时传入的参数的数量和类型应和定义函数时设置的数量和类型相符。

如果要接收函数的返回值,可以用一个变量来保存返回值,语法格式如下。

复制代码
let 变量名: 类型 = 函数名(参数1, 参数2, …);

一个函数的返回值也可以作为参数传给另一个函数,示例代码如下。

复制代码
函数名2(函数名1(参数1, 参数2, …))

需要说明的是,在程序中定义函数和调用函数的编写顺序不分前后。

下面通过代码演示函数的定义与调用,示例代码如下。

TypeScript 复制代码
// 定义函数
function sum(num1: number, num2: number): number {
  return num1 + num2;
}
// 调用函数
console.log('', sum(1, 2));     // 输出结果:3

函数的返回值可以赋值给变量,从而将函数的返回值保存下来,在保存时,变量的类型可以自动推断,如果遇到无法自动推断的情况,在函数调用的小括号后面加上"as 类型"进行类型断言,示例代码如下。

TypeScript 复制代码
function sum1(num1: number, num2: number) {
  return num1 + num2;
}
let n1 = sum1(1, 2);            // 自动推断
let n2 = sum1(1, 2) as number;      // 类型断言

2.7.3 将函数作为值使用

ArkTS中的函数可以作为值使用。例如,将函数作为变量值、参数值、返回值或数组元素值等。

在将函数作为值使用时,可以设置类型,也可以省略类型,ArkTS会自动推断类型。

若要设置类型,可以将函数的类型写成如下形式。

复制代码
(参数1: 类型, 参数2: 类型, …) => 返回值类型

由于上述形式比较长,写起来麻烦,可以利用type关键字将类型定义出来。type关键字用于定义一个自定义的类型,语法格式如下。

复制代码
type 类型名 = 类型;

下面通过代码演示如何将函数作为变量值使用,示例代码如下。

TypeScript 复制代码
function func(num1: number, num2: number) {
  return num1 + num2;
}
let s1 = func;          // 自动推断类型
let s2: (num1: number, num2: number) => number = func;        // 设置类型
type T = (num1: number, num2: number) => number;
let s3: T = func;           // 设置自定义的类型
console.log('', s1(1, 2));      // 输出结果:3
console.log('', s2(1, 2));      // 输出结果:3
console.log('', s3(1, 2));      // 输出结果:3

将函数作为参数值、返回值、数组元素值的示例代码如下。

TypeScript 复制代码
// 将函数作为参数值
type T1 = (num1: number, num2: number) => number;
function fn(sum: T1) {
  // 将函数作为返回值
  return sum;
}
function sum(num1: number, num2: number) {
  return num1 + num2;
}
console.log('', fn(sum)(1, 2)); // 输出结果:3
// 将函数作为数组元素值
function sumFn(num1: number, num2: number) {
  return num1 + num2;
}
let arr1 = [sumFn];
console.log('', arr1[0](1, 2));         // 输出结果:3

当在一个函数中调用了通过参数传过来的函数时,这个通过参数传过来的函数被称为回调(callback)函数,示例代码如下。

TypeScript 复制代码
type T2 = (num1: number, num2: number) => number;
function func1(num1: number, num2: number) {
  return num1 + num2;
}
function sumFn1(sum: T2, num1: number, num2: number) {
  return sum(num1, num2);
}
console.log('', sumFn1(func1, 1, 2));       // 输出结果:3

2.7.4 箭头函数

箭头函数是一种简化的定义函数的语法,它可以作为表达式的一部分使用。

箭头函数的语法特点是有"=>"箭头。通常,箭头函数的语法格式以小括号开头,在小括号中放置参数,小括号后面跟着箭头"=>",箭头后面跟着"{}","{}"里面是函数体。

箭头函数的具体语法格式如下。

复制代码
(参数1: 类型, 参数2: 类型, …): 返回值类型 => {
  函数体
}

将箭头函数赋给变量后,可以通过"变量名()"的方式实现箭头函数的调用。

下面通过代码演示箭头函数的使用方法,示例代码如下。

TypeScript 复制代码
let sum3 = (num1: number, num2: number) => {
  return num1 + num2;
};
console.log('', sum3(1, 2));        // 输出结果:3

在箭头函数中,当函数体只有一条语句,且该语句的运行结果就是函数的返回值时,可以省略函数体的大括号和return关键字,示例代码如下。

TypeScript 复制代码
let sum4 = (num1: number, num2: number) => num1 + num2;
console.log('', sum4(1, 2));        // 输出结果:3

将箭头函数用小括号"()"标识后,可以在其后面加上小括号进行传递参数和函数调用,这种方式称为函数自调用,示例代码如下。

TypeScript 复制代码
((num1: number, num2: number) => {
  console.log('', num1 + num2);
})(1, 2);   // 输出结果:3

2.7.5 常用的内置函数

ArkTS提供了一些内置函数,方便开发者使用。

  • parseInt()

  • parseFloat()

  • setTimeout()和setInterval()

  • clearTimeout()和clearInterval()

parseInt()

使用parseInt()函数可以将给定的数据转换为number类型的数据,并且直接省略数据的小数部分,返回数据的整数部分,示例代码如下。

TypeScript 复制代码
console.log('', parseInt('100.56'));        // 输出结果:100

parseInt()函数还可以自动识别进制,示例代码如下。

TypeScript 复制代码
console.log('', parseInt('0xF'));       // 输出结果:15
  1. parseFloat()

使用parseFloat()函数可以将给定的数据转换为number类型的浮点数,示例代码如下。

TypeScript 复制代码
console.log('', parseFloat('100.56'));      // 输出结果:100.56
console.log('', parseFloat('314e-2'));      // 输出结果:3.14
  1. setTimeout()和setInterval()

setTimeout()函数用于设置定时器,实现在达到指定时间后执行代码的功能。

该函数的第1个参数表示要执行的代码,第2个参数表示指定的时间,单位为毫秒。 该函数的返回值为定时器的标识。

setInterval()函数与setTimeout()函数类似,唯一的区别是setInterval()函数会以指定的时间为周期重复执行代码,而setTimeout()函数只会执行一次代码。

下面通过代码演示setTimeout()函数和setInterval()函数的使用方法,示例代码如下。

TypeScript 复制代码
let timer1 = setTimeout(() => {
  console.log('1秒后输出1次');
}, 1000);
let timer2 = setInterval(() => {
  console.log('每隔1秒输出1次');
}, 1000);

在开发中有同步操作和异步操作的概念。

同步操作是指每个操作按先后顺序依次执行。 异步操作是某个操作并不会立即执行,而是等某个时机成熟后再执行。其优势是不会阻塞代码的执行流程。

setInterval()函数和setTimeout()函数的第1个参数中的代码就属于异步操作,当这两个函数被调用时,它们会立即执行完成,然后继续执行它们后面的代码,直到到达指定时间后,才会执行第1个参数中的代码。

  1. clearTimeout()和clearInterval()

clearTimeout()函数用于清除由setTimeout()函数设置的定时器。 clearInterval()函数用于清除由setInterval()函数设置的定时器。

这两个函数都只有1个参数,表示要清除的定时器的标识。当清除定时器后,定时器的代码将不会执行。

下面以clearInterval()函数为例进行演示,示例代码如下。

TypeScript 复制代码
let timer = setInterval(() => {
  console.log('1秒后输出1次');
  clearInterval(timer);
}, 1000);

2.8 变量的作用域和闭包

2.8.1 变量的作用域

通过前面的学习可知,变量需要声明后才能使用,但这并不意味着声明变量后就可以在任意位置使用该变量,变量的可用范围取决于变量的作用域。

在大括号"{}"中,使用let关键字声明的变量称为块级变量,具有块级作用域,仅在大括号"{}"中有效,如if语句、for语句、while语句、函数等的"{}"中。

例如,定义一个info()函数,并在该函数中声明一个student变量,在info()函数外是无法访问student变量的,示例代码如下。

TypeScript 复制代码
function info() {
  let student = '小智';
}
info();
console.log(student);           // 错误代码

变量的作用域可以向内传递,即从函数内部可以访问函数外部声明的变量,但从函数外部不能访问函数内部声明的变量,示例代码如下。

TypeScript 复制代码
let num1 = 1;
function fn1() {
  let num2 = 2;
  let fn2 = () => {
    console.log('', num1 + num2);
  };
  fn2();
}
fn1();      // 输出结果:3

2.8.2 闭包

当一个函数访问了外部的变量或函数时,就会形成闭包(Closure)。

简单来说,闭包就是由函数和这个函数访问的外部的变量或函数组成的一个整体。

通过闭包,可以让开发者由内层函数访问外层函数中的变量和函数,其中,内层函数被称为闭包函数。

当把闭包函数作为返回值返回后,只要闭包函数一直被使用,闭包函数所访问的变量和函数就始终在内存中。

下面通过一个统计闭包函数被调用的次数的例子进行演示,示例代码如下。

TypeScript 复制代码
function fn01() {
  let num = 0;
  return () => {
    ++num;
    console.log(`第${num}次被调用`);
  }
}
let fn02 = fn01();
fn02();     // 输出结果:第1次被调用
fn02();     // 输出结果:第2次被调用
fn02();     // 输出结果:第3次被调用

2.9 阶段案例------统计每个学生的总成绩

期末考试结束后,老师经常需要统计班级中每个学生的总成绩。本案例将利用二维数组保存下列学生的成绩,并通过遍历二维数组的方式对每个学生的成绩进行求和。

① 小明:语文成绩为90,数学成绩为99,英语成绩为95。 ② 小智:语文成绩为98,数学成绩为100,英语成绩为85。 ③ 小红:语文成绩为95,数学成绩为96,英语成绩为97。

本章小结

本章讲解的内容主要包括初识ArkTS,调试输出和注释,变量、常量和数据类型,运算符,流程控制,数组和枚举,函数,变量的作用域和闭包。通过本章的学习,读者应该能够掌握ArkTS的基础语法,能够运用ArkTS编写简单的程序。

相关推荐
新元代码2 小时前
探秘鸿蒙南向开发:Hi3861 架构、编译与实战全解析
华为·架构·harmonyos
笔触狂放2 小时前
第1章 初识鸿蒙
华为·harmonyos
小雨青年4 小时前
【HarmonyOS 7 沉浸光感深度实战】 06 复杂背景下的自动反色与可读性处理
华为·harmonyos
水深火乐4 小时前
HmarkX(码笺)的本地数据库模块重构实战
harmonyos
大锅盖14 小时前
Map 搜索没有返回可信候选时,派单页面该怎么继续工作
华为·harmonyos
长江&后浪4 小时前
华为wlan实验-三层旁挂
运维·服务器·网络·华为
HarmonyOS_SDK5 小时前
HarmonyOS SDK API诊断 Skill,一键定位功能故障问题
harmonyos
大锅盖15 小时前
Canvas 签名板里的 antialias 开关,怎样确保它真正触发重绘
华为·harmonyos
M-Robots echo6 小时前
王成录:黑客松不只是赛事,是开源机器人生态快速试错、挖掘创新的试验场
机器人·ros·鸿蒙·具身智能·开源社区·m-robots