《HarmonyOS NEXT应用开发实践(视频教学版)(编程与应用开发丛书)》(王树生)【摘要 书评 试读】- 京东图书
目录
[3.1 ArkTS语言及其基本组成](#3.1 ArkTS语言及其基本组成)
[3.1.1 ArkTS语言简介](#3.1.1 ArkTS语言简介)
[3.1.2 ArkTS的基本组成](#3.1.2 ArkTS的基本组成)
[3.2 声 明](#3.2 声 明)
[3.2.1 变量、常量与自动类型推断](#3.2.1 变量、常量与自动类型推断)
[3.2.2 数据类型](#3.2.2 数据类型)
[1. number类型](#1. number类型)
[2. boolean类型](#2. boolean类型)
[3. string类型](#3. string类型)
[4. void类型](#4. void类型)
[5. Object类型](#5. Object类型)
[6. array类型](#6. array类型)
[7. enum类型](#7. enum类型)
[8. Union类型](#8. Union类型)
[9. Aliases类型](#9. Aliases类型)
3.1 ArkTS语言及其基本组成
ArkTS是一种为构建高性能应用而设计的编程语言。它在TypeScript语法的基础上进行了优化,以提供更高的性能和开发效率。
3.1.1 ArkTS语言简介
目前流行的编程语言TypeScript是在JavaScript(JS)基础上通过添加类型定义扩展而来的,而ArkTS则是TypeScript(TS)的进一步扩展。TypeScript之所以深受开发者的喜爱,是因为它提供了一种更结构化的JavaScript编码方法。ArkTS旨在保持TypeScript的大部分语法,为现有的TypeScript开发者实现无缝过渡,让移动开发者快速上手ArkTS。ArkTS、TypeScript和JavaScript三者之间的关系如图3-1所示。

图3-1 ArkTS、TypeScript与JavaScript的关系
ArkTS的一大特性是它专注于低运行时开销。ArkTS对TypeScript的动态类型特性施加了更严格的限制,以减少运行时开销,提高执行效率。通过取消动态类型特性,ArkTS代码能更有效地被运行前编译和优化,从而实现更快的应用启动和更低的功耗。
与JavaScript的互通性是ArkTS语言设计中的关键考虑因素。鉴于许多移动应用开发者希望重用其TypeScript和JavaScript代码和库,ArkTS提供了与JavaScript的无缝互通,使开发者可以很容易地将JavaScript代码集成到他们的应用中。这意味着开发者可以利用现有的代码和库进行ArkTS开发。
为了确保应用开发的最佳体验,ArkTS提供对方舟开发框架ArkUI的声明式语法和其他特性的 支持。
从API Version 10开始,ArkTS进一步通过规范强化静态检查与分析能力。与标准TypeScript的差异可参考官方文档中的"从TypeScript到ArkTS的适配规则"。
- 强制使用静态类型:静态类型是ArkTS的重要特性之一。如果使用静态类型,那么程序中变量的类型就是确定的。同时,由于所有类型在程序实际运行前都是已知的,编译器可以验证代码的正确性,从而减少运行时的类型检查,有助于性能提升。
- 禁止在运行时改变对象布局:为实现最大性能,ArkTS要求在程序执行期间不能更改对象布局。
- 限制运算符语义:为获得更好的性能并鼓励开发者编写更清晰的代码,ArkTS限制了一些运算符的语义。比如,一元加法运算符只能作用于数字,不能用于其他类型的变量。
- 不支持结构化类型(Structural Typing):对结构化类型的支持需要在语言、编译器和运行时进行仔细的考虑和实现,当前ArkTS不支持该特性。未来官方可能会根据实际场景的需求和反馈,再重新考虑是否支持结构化类型。
当前,在UI开发框架中,ArkTS主要扩展了如下能力:
- 基本语法:ArkTS定义了声明式UI描述、自定义组件和动态扩展UI元素的能力,再配合ArkUI开发框架中的系统组件及其相关的事件方法、属性方法等,共同构成了UI开发的主体。
- 状态管理:ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活地利用这些能力来实现数据和UI的联动。
- 渲染控制:ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的UI内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。数据懒加载从数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。
ArkTS兼容TypeScrip/JavaScript生态,开发者可以使用TypeScrip/JavaScript进行开发或复用已有 代码。
未来,ArkTS会结合应用开发/运行的需求持续演进,逐步提供并行和并发能力增强、系统类型增强、分布式开发范式等更多特性。
3.1.2 ArkTS的基本组成
ArkTS的基本组成和组件名称如图3-2所示。

图3-2 ArkTS的基本组成及组件名称
组成一个基本ArkTS结构的各类装饰器和组件的含义说明如下:
- 装饰器:用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如@Component、@Entry和@State都是装饰器,@Component表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组件中的状态变量,状态变量变化会触发UI刷新。
- UI描述:以声明的方式来描述UI的结构,例如build()方法中的代码块。
- 系统组件:ArkUI框架中默认内置的基础和容器组件,可直接被开发者调用,比如示例中的Column、Text、Divider、Button。
- 属性方法:组件可以通过链式调用配置多项属性,如fontSize()、width()、height()、backgroundColor()等。
- 事件方法:组件可以通过链式调用设置多个事件的响应逻辑,如跟随在Button后面的onClick()。
- 自定义组件:可复用的UI单元,可组合其他组件,如被@Component装饰的struct Hello。
自定义组件、系统组件、属性方法、事件方法的具体使用可参考官方文档中的"基于ArkTS的声明式开发范式"。除此之外,ArkTS扩展了多种语法范式来使开发更加便捷,具体可查阅官方文档。
3.2 声 明
ArkTS通过声明引入变量、常量、函数和类型。
3.2.1 变量、常量与自动类型推断
- 变量
以关键字let开头的声明引入变量,该变量在程序执行期间可以具有不同的值。例如:
const mTag: string = 'Ch03Ability================';
let hi: string = 'hello';
hi = 'hello, world';
hilog.error(0x0000, mTag,mTag + '%{public}s',hi);- 常量
以关键字const开头的声明引入只读常量,该常量只能被赋值一次。例如:
const mTag: string = 'Ch03Ability================';对常量重新赋值会造成编译时错误。
- 自动类型推断
由于ArkTS是一种静态类型语言,因此所有数据的类型都必须在编译时确定。但是,如果一个变量或常量的声明包含了初始值,那么开发者就不需要显式指定其类型。ArkTS规范中列举了所有允许自动推断类型的场景。
在以下示例中,两条声明语句都是有效的,两个变量都是string类型:
let hi1: string = 'hello';
let hi2 = 'hello, world';3.2.2 数据类型
1. number类型
ArkTS提供number类型,任何整数和浮点数都可以被赋给此类型的变量。数字字面量包括整数字面量和十进制浮点数字面量。
整数字面量包括以下类别:
- 由数字序列组成的十进制整数。例如:0、117、-345。
- 以0x(或0X)开头的十六进制整数,可以包含数字(0~9)和字母a~f或A~F。例如:0x1123、0x00111、-0xF1A7。
- 以0o(或0O)开头的八进制整数,只能包含数字(0~7)。例如:0o777。
- 以0b(或0B)开头的二进制整数,只能包含数字0和1。例如:0b11、0b0011、-0b11。
浮点字面量包括以下内容:
- 十进制整数,可为有符号数(即前缀为"+"或"-")。
- 小数点(".")。
- 小数部分(由十进制数字字符串表示)。
- 以"e"或"E"开头的指数部分,后跟有符号(即前缀为"+"或"-")或无符号整数。
例如:
let n1 = 3.14;
let n2 = 3.141592;
let n3 = .5;
let n4 = 1e2;
function factorial(n: number): number {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}
factorial(n1)  //  7.660344000000002
factorial(n2)  //  7.680640444893748
factorial(n3)  //  1
factorial(n4)  //  9.33262154439441e+1572. boolean类型
boolean类型由true和false两个逻辑值组成。
通常在条件语句中使用boolean类型的变量:
let isDone: boolean = false;
// ...
if (isDone) {
  console.log ('Done!');
}3. string类型
String代表字符序列;可以使用转义字符来表示字符。字符串字面量由单引号(')或双引号(")引起来的零个或多个字符组成。字符串字面量还有一种特殊形式,是用反向单引号(`)引起来的模板字面量。例如:
let s1 = 'Hello, world!\n';
let s2 = 'this is a string';
let a = 'Success';
let s3 = `The result is ${a}`; 4. void类型
void类型用于指定函数没有返回值。此类型只有一个值,同样是void。由于void是引用类型,因此它可以用于泛型类型参数。例如:
class Class<T> {
  //...
}
let instance: Class <void>5. Object类型
Object类型是所有引用类型的基类型。任何值,包括基本类型的值(它们会被自动装箱),都可以直接被赋给Object类型的变量。
6. array类型
array,即数组,是由可赋值给数组声明中指定的元素类型的数据组成的对象。数组可由数组复合字面量(即用方括号括起来的零个或多个表达式的列表,其中每个表达式为数组中的一个元素)来赋值。数组的长度由数组中元素的个数来确定。数组中第一个元素的索引为0。
以下示例将创建包含3个元素的数组:
let names: string[] = ['Alice', 'Bob', 'Carol'];7. enum类型
enum类型,又称枚举类型,是预先定义的一组命名值的值类型,其中命名值又称为枚举常量。使用枚举常量时必须以枚举类型名称为前缀。例如:
enum ColorSet { Red, Green, Blue }
let c: ColorSet = ColorSet.Red;常量表达式可用于显式设置枚举常量的值。例如:
enum ColorSet { White = 0xFF, Grey = 0x7F, Black = 0x00 }
let c: ColorSet = ColorSet.Black;8. Union类型
Union类型,即联合类型,是由多个类型组合成的引用类型。联合类型包含了变量可能的所有 类型。例如:
class Cat {
  // ...
}
class Dog {
  // ...
}
class Frog {
  // ...
}
type Animal = Cat | Dog | Frog | number
// Cat、Dog、Frog是一些类型(类或接口)
let animal: Animal = new Cat();
animal = new Frog();
animal = 42;
// 可以将类型为联合类型的变量赋值为任何组成类型的有效值
可以用不同的机制获取联合类型中特定类型的值。例如:
class Cat { sleep () {}; meow () {} }
class Dog { sleep () {}; bark () {} }
class Frog { sleep () {}; leap () {} }
type Animal = Cat | Dog | Frog
function foo(animal: Animal) {
  if (animal instanceof Frog) {
    animal.leap();  // animal在这里是Frog类型
  }
  animal.sleep(); // Animal具有sleep方法
}9. Aliases类型
Aliases类型为匿名类型(数组、函数、对象字面量或联合类型)提供名称,或为已有类型提供替代名称。例如:
type Matrix = number[][];
type Handler = (s: string, no: number) => string;
type Predicate <T> = (x: T) => boolean;
type NullableObject = Object | null;
