HarmonyOS应用开发实战(基础篇)Day01-《ArkTS基本知识》

ArkTS基本知识


1、ArkTS语言特点

参考文档:ArkTS语言介绍

ArkTS 是华为为鸿蒙生态(HarmonyOS)打造的主力应用开发语言,它在 TypeScript 的基础上进行了深度扩展和约束,以更好地适配声明式 UI 编程模型(如 ArkUI)并提升运行时性能与类型安全性。因此,ArkTS 并非完全兼容 TypeScript,而是"TypeScript 的超集 + 静态强类型增强 + 运行时优化限制"。

下面通过两个典型特性,展示 ArkTS 与标准 TypeScript 的关键差异。

1.1、对象字面量必须标注类型

在 TypeScript 中,对象字面量的类型通常可以通过类型推导 自动确定,开发者无需显式声明。但在 ArkTS 中,出于编译期类型安全运行时性能优化 的考虑,所有对象字面量都必须显式标注其类型

我们来看一段相同代码在两种环境下的表现:

ts 复制代码
const stu = {
  name: 'zhangsan',
  age: 19
}

在 ArkTS 中,编译器会报错,提示"对象字面量必须具有显式类型注解":

而在标准 TypeScript 环境中,这段代码完全合法,不会产生任何错误:

因此,在 ArkTS 中,正确的写法应为:

ts 复制代码
interface Student {
  name: string;
  age: number;
}

const stu: Student = {
  name: 'zhangsan',
  age: 19
};

或直接内联类型注解:

ts 复制代码
const stu: { name: string; age: number } = {
  name: 'zhangsan',
  age: 19
};

这种方式虽然略显冗余,但能确保编译器在早期捕获潜在的类型错误,并为后续的 AOT(Ahead-of-Time)编译提供更精确的类型信息。

1.2、不支持 Structural Typing(结构化类型)

TypeScript 采用的是 structural typing(结构化类型),也称为"鸭子类型"------只要两个类型的结构兼容(即拥有相同的属性和方法),就可以互相赋值,即使它们没有继承关系或显式声明。

而 ArkTS 不支持 structural typing ,它要求类型匹配必须是名义上的(nominal)或显式兼容的。这意味着,即使一个对象包含了接口所需的所有字段,只要其类型未被明确声明为该接口或其子类型,ArkTS 就会拒绝接受。

示例代码如下:

ts 复制代码
interface Ani {
  name: string,
  age: number,
}
function getName(obj: Ani) {
  return obj.name;
}

const ani = { name: 'zhangsan', age: 18, gender: '男' };

getName(ani);

在 TypeScript 中,ani 虽然多了一个 gender 属性,但由于它包含 Ani 接口所需的全部字段,因此可以顺利通过类型检查:

但在 ArkTS 中,这段代码会报错,提示类型不匹配:

解决方法是:要么将 ani 显式声明为 Ani 类型(此时不能包含额外属性),要么扩展接口以包含所有实际字段:

ts 复制代码
interface Ani {
  name: string;
  age: number;
  gender: string; // 显式声明所有字段
}

注:为了避免变量名与接口名冲突,示例中已将接口重命名为 Ani(首字母大写)。

这种设计虽然牺牲了一定的灵活性,但换来了更强的类型安全性和更高效的运行时性能,尤其适合资源受限的嵌入式设备和高性能 UI 渲染场景。


2、ArkTS基本数据类型

ArkTS 支持多种基础数据类型,这些类型与 JavaScript/TypeScript 基本一致,但在使用上可能有更严格的约束。

2.1、number 类型

ArkTS 中的 number 类型用于表示整数和浮点数,底层统一使用 64 位双精度浮点数(IEEE 754 标准)。支持十进制、科学计数法、小数等多种字面量形式。

2.2、boolean 类型

boolean 类型仅有两个取值:truefalse,主要用于控制程序流程,如条件判断、循环控制等。ArkTS 不允许将非布尔值(如数字、字符串)隐式转换为布尔值,必须显式判断。

2.3、string 类型

string 类型用于表示文本数据。ArkTS 支持三种字符串字面量:

  • 单引号 '...'
  • 双引号 "..."
  • 反引号 ...(模板字符串,支持 ${表达式} 插值)

字符串中的特殊字符(如换行 \n、制表符 \t)需使用转义序列表示。

以下是一个完整的 UI 示例,展示了如何在 ArkTS 组件中使用这些基本类型:

ts 复制代码
@Entry
@Component
struct Index {
  build() {
    Column(){
      Button('数字类型').onClick(()=>{
        let n1 = 3.14;
        let n2 = 3.141592;
        let n3 = 0.5;
        let n4 = 1e2; // 科学计数法:100
        console.log('数字类型', n1);
        console.log('数字类型', n2);
        console.log('数字类型', n3);
        console.log('数字类型', n4);
      })

      Button('布尔类型').onClick(()=>{
        let isFDone: boolean = false;
        let isTDone: boolean = true;
        console.log('布尔类型', isFDone);
        console.log('布尔类型', isTDone);
      })

      Button('字符串类型').onClick(()=>{
        let s1 = 'Hello, world!\n'; // 包含换行符
        let s2 = 'this is a string';
        let a = 'Success';
        let s3 = `The result is ${a}`; // 模板字符串插值

        console.log('字符串类型', s1);
        console.log('字符串类型', s2);
        console.log('字符串类型', a);
        console.log('字符串类型', s3);
      })
    }
  }
}

3、高级数据类型

除了基本类型,ArkTS 还提供了多种复合类型,用于构建更复杂的数据结构。

3.1、枚举类型(enum)

枚举(enum)是一种定义命名常量集合的方式,有助于提高代码可读性和维护性。ArkTS 支持字符串枚举和数值枚举,推荐使用字符串枚举,因其更具语义且不易受顺序变更影响。

使用时必须通过 EnumName.Value 的形式访问,不能直接使用字符串字面量替代(除非显式比较)。

3.2、联合类型(Union Types)

联合类型使用 | 符号连接多个类型,表示一个变量可以是其中任意一种类型。例如 string | number 表示该变量既可以是字符串,也可以是数字。

这在处理可能返回多种结果的函数(如 API 响应、用户输入)时非常有用。

3.3、数组类型(Array)

数组是存储有序元素的集合。ArkTS 支持两种数组声明方式:

  • let arr: number[] = [1, 2, 3];
  • let arr: Array<string> = ['a', 'b'];

数组支持动态扩容(如 arr[100] = 100),但出于性能考虑,建议预先分配合理大小。


4、运算符

ArkTS 支持丰富的运算符,用于执行各种计算和逻辑操作。

4.1、赋值运算符

基础赋值:x = y

复合赋值(结合算术或位运算):

  • +=, -= , *= , /= , %=
  • <<=, >>=, >>>=(位移)
  • &=, |=, ^=(位运算)

这些运算符在简化代码的同时,也提升了执行效率。

4.2、比较运算符

用于比较两个值的大小或相等性,返回布尔结果:

  • >, <, >=, <=
  • ==, !=(值相等)
  • ===, !==(严格相等,推荐使用)

注意:ArkTS 强烈建议使用 ===!==,避免因类型转换导致意外行为。


4.3、位运算符

对整数的二进制位进行操作,常用于权限控制、标志位设置等底层场景:

  • &(按位与)
  • |(按位或)
  • ^(按位异或)
  • ~(按位取反)
  • <<(左移)、>>(带符号右移)、>>>(无符号右移)


4.4、逻辑运算符

用于组合多个布尔表达式:

  • &&(逻辑与):全真才真
  • ||(逻辑或):一真即真
  • !(逻辑非):取反

支持短路求值(short-circuit evaluation),即在结果确定后不再计算后续表达式。


4.5、算术运算符

执行基本数学运算:

  • +, -, *, /, %(取余)
  • ++, --(自增/自减)

注意:+ 也可用于字符串拼接,但混合类型操作需谨慎。


5、语句

ArkTS 支持常见的程序控制语句,用于实现逻辑分支与循环。

5.1、条件语句(if / else)

根据布尔表达式的值决定是否执行某段代码。可嵌套使用,也可配合三元运算符简化简单判断。

5.2、循环语句(for)

for 循环适用于已知迭代次数的场景,由初始化、条件判断、更新表达式三部分组成。

5.3、while 语句

当循环次数不确定,但满足某个条件时持续执行,适合处理动态数据流或用户交互。

5.4、throw 和 try 语句

用于异常处理。throw 抛出错误,try...catch 捕获并处理异常,防止程序崩溃。

注意:ArkTS 中的异常处理主要用于调试和边界情况,不建议在常规逻辑中频繁使用。

5.5、switch 语句

多分支选择结构,比多个 if-else 更清晰。每个 case 必须以 break 结束,否则会"穿透"到下一个分支。

支持字符串、数字、枚举等类型作为判断条件。


代码部分

以下为完整示例代码,涵盖上述所有知识点。当前被注释掉的部分可根据需要逐步启用,用于测试不同功能模块。

ts 复制代码
@Entry
@Component
struct Index {
  build() {
    Column(){
      // 数据类型
      /*

      Button('数字类型').onClick(()=>{
        let n1 = 3.14;
        let n2 = 3.141592;
        let n3 = 0.5;
        let n4 = 1e2;
        console.log('数字类型',n1);
        console.log('数字类型',n2);
        console.log('数字类型',n3);
        console.log('数字类型',n4);
      })

      Button('布尔类型').onClick(()=>{
        let isFDone: boolean = false;
        let isTDone: boolean = true;
        console.log('布尔类型',isFDone);
        console.log('布尔类型',isTDone);
      })

      Button('字符串类型').onClick(()=>{
        let s1 = 'Hello, world!\n';
        let s2 = 'this is a string';
        let a = 'Success';
        let s3 = `The result is ${a}`;

        console.log('字符串类型',s1)
        console.log('字符串类型',s2)
        console.log('字符串类型',a)
        console.log('字符串类型',s3)
      })

      Button('枚举类型').onClick(()=>{
        let grade = Grade.优
        if (grade == 'A') {
          console.log('枚举类型:优');
        }else {
          console.log('枚举类型:错误');
        }
      })

      Button('联合类型').onClick(()=>{
        let GradeAll : string | number | null = 1;
        console.log('联合类型',GradeAll)
        GradeAll = null;
        console.log('联合类型',GradeAll)
        GradeAll = "A";
        console.log('联合类型',GradeAll)
      })

      Button('数组类型').onClick(()=>{
        // 数组定义
        let arr:string[] = ['1','2','3','4']
        let arr2: number[] = new Array(10)
        // 下标
        console.log('数组类型',arr[3]);
        // 支持动态扩容
        arr2[100]=100
        console.log('数组类型',arr2.length);
      })
      */

      // 运算符
      /*
      // 赋值运算符
      Button('赋值运算符').onClick(()=>{
        let a:number = 10
        let b:number = 20
        let c:number = 30
        console.log('赋值运算符',a,b,c);
      })

      // 算数运算符
      Button('算数运算符').onClick(()=>{
        let a = 10
        let b = 20
        console.log('算数运算符:加法',a+b);
        console.log('算数运算符:减法',a-b);
        console.log('算数运算符:乘法',a*b);
        console.log('算数运算符:除法',a/b);
        console.log('算数运算符:取余',a%b);
        console.log('算数运算符:自增',a++);
        console.log('算数运算符:自减',a--);
      })

      // 比较运算符
      Button('比较运算符').onClick(()=>{
        let a = 10
        let b = 20
        console.log('大于',a>b);
        console.log('小于',a<b);
        console.log('等于',a==b);
        console.log('不等于',a!=b);
        console.log('大于等于',a>=b);
        console.log('小于等于',a<=b);
      })

      // 逻辑运算符
      Button('逻辑运算符').onClick(()=>{
        let a = 10
        let b = 20
        console.log('逻辑与',a>5 && b>10);
        console.log('逻辑或',a>5 || b>10);
        console.log('逻辑非',!(a>5));
      })

      // 位运算符
      Button('位运算符').onClick(()=>{
        let a = 10
        let b = 20
        console.log('按位与',a&b);
        console.log('按位或',a|b);
        console.log('按位异或',a^b);
        console.log('按位取反',~a);
        console.log('左移',a<<1);
        console.log('右移',a>>1);
      })
      */
      // 语句
      /*
      Button('条件语句').onClick(()=>{
        let grade = Grade.优
        if (grade == 'A') {
          console.log('枚举类型:优');
        }else {
          console.log('枚举类型:错误');
        }
      })

      // 循环
      Button('循环语句').onClick(()=>{
        for (let i = 0; i < 10; i++) {
          console.log('循环语句',i);
        }
      })

      // while循环
      Button('while循环').onClick(()=>{
        let i = 0
        while (i < 10) {
          console.log('while循环',i);
          i++
        }
      })

      //throw和try语句
      Button('throw和try语句').onClick(()=>{
        try {
          throw new Error('throw和try语句');
        }catch (e){
          console.log(e.message);
        }
      })

      //switch语句
      Button('switch语句').onClick(()=>{
        let grade = 'A'
        switch (grade) {
          case 'A':
            console.log('switch语句:优');
            break;
          case 'B':
            console.log('switch语句:良');
            break;
          case 'C':
            console.log('switch语句:中');
            break;
          case 'D':
            console.log('switch语句:差');
            break;
        }
      })
      
      */
    }
  }
}
enum Grade{
  '优'='A',
  '良'='B',
  '中'='C',
  '差'='D',
}
相关推荐
BlackWolfSky3 小时前
鸿蒙高级课程笔记2—应用性能优化
笔记·华为·harmonyos
玄同7653 小时前
Python Random 模块深度解析:从基础 API 到 AI / 大模型工程化实践
人工智能·笔记·python·学习·算法·语言模型·llm
符哥20083 小时前
C++ 适合初学者的学习笔记整理
c++·笔记·学习
ujainu3 小时前
护眼又美观:Flutter + OpenHarmony 鸿蒙记事本一键切换夜间模式(四)
android·flutter·harmonyos
一只大侠的侠3 小时前
Flutter开源鸿蒙跨平台训练营 Day 13从零开发注册页面
flutter·华为·harmonyos
曦月逸霜3 小时前
Python快速入门——学习笔记(持续更新中~)
笔记·python·学习
森之鸟3 小时前
鸿蒙审核常见问题避坑指南_Scroll嵌套List_Grid滑动优化
华为·harmonyos
AI视觉网奇3 小时前
blender 导入fbx 黑色骨骼
学习·算法·ue5·blender
星火开发设计3 小时前
this 指针:指向对象自身的隐含指针
开发语言·数据结构·c++·学习·指针·知识