跳到主要内容

第二章:ArkTS 基础语法

本章配套代码:code/Chapter2(学生成绩计算 Demo) 前置要求:已完成第一章开发环境搭建

2.1 学习目标

  • 掌握 ArkTS 数据类型、变量与类型推断
  • 理解函数、类、接口、泛型的正确用法
  • 掌握数组方法与控制流
  • 通过综合示例(学生成绩管理)巩固语法

2.2 ArkTS 概述

ArkTS 是 HarmonyOS 应用开发的官方编程语言,基于 TypeScript 扩展而来,专为声明式 UI 开发优化。

TypeScript ──约束──> ArkTS ──扩展──> ArkUI 声明式开发

与 TypeScript 的核心差异:

特性TypeScriptArkTS
any/unknown支持❌ 不支持(静态类型安全)
对象字面量类型宽松需显式类型标注
结构性类型支持受限(需类或接口)
联合类型/类型别名支持支持(type/interface
泛型支持支持

💡 ArkTS 通过限制 any 实现强类型安全,这是它区别于 TS 的最大特点。

2.3 数据类型

2.3.1 基础类型

// 布尔类型
let isDone: boolean = false

// 数字类型(整数/浮点/NaN/Infinity)
let count: number = 42
let price: number = 9.99
let negative: number = -3.14

// 字符串类型(单引号/双引号/模板字符串)
let name: string = '张三'
let greeting: string = `你好,${name}`

// 数组类型(两种写法)
let scores: number[] = [90, 85, 92]
let names: Array<string> = ['Alice', 'Bob']

2.3.2 复合类型

// 元组:固定长度、固定类型
let person: [string, number] = ['张三', 25]
console.log(person[0]) // 张三
console.log(person[1]) // 25

// 枚举
enum Direction {
Up = 1,
Down,
Left,
Right
}
let dir: Direction = Direction.Up

// 接口:描述对象结构
interface User {
name: string
age: number
email?: string // 可选属性
readonly id: number // 只读属性
}

// 类型别名:联合类型
type ID = string | number
type Status = 'active' | 'inactive' // 字符串字面量联合

类型选择建议:

场景推荐类型
对象结构interface
简单联合type
固定长度元组元组 [T1, T2]
有限取值枚举或字符串字面量联合

2.4 变量声明

// let:可变变量(推荐默认使用)
let age: number = 25
age = 26 // ✅ 可以修改

// const:常量,初始化后不可变
const PI: number = 3.14
// PI = 3.14159 // ❌ 编译错误

// 类型推断:显式声明更安全
let inferred = 'hello' // 推断为 string
let explicit: string = 'hello' // 显式声明

⚠️ ArkTS 建议始终显式声明类型,避免依赖推断导致的歧义。组件内状态变量(@Local 等)也要求显式类型。

2.5 函数

2.5.1 函数定义

// 具名函数
function add(a: number, b: number): number {
return a + b
}

// 箭头函数(推荐用于回调)
const multiply = (a: number, b: number): number => a * b

// 异步函数
async function fetchData(): Promise<string> {
return 'data'
}

2.5.2 参数处理

// 默认参数
function greet(name: string = 'World'): string {
return `Hello, ${name}!`
}

// 可选参数(置于参数列表末尾)
function buildUrl(path: string, protocol?: string): string {
return `${protocol ?? 'https'}://example.com${path}`
}

// 剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((a, b) => a + b, 0)
}
console.log(sum(1, 2, 3, 4)) // 10

💡 ??(空值合并)与 ?.(可选链)是 ArkTS 常用操作符,避免空值异常。

2.6 类

2.6.1 类定义

class Person {
name: string
private age: number
static species: string = 'Human' // 静态属性

constructor(name: string, age: number) {
this.name = name
this.age = age
}

greet(): string {
return `我是${this.name},今年${this.age}`
}

static create(name: string): Person { // 静态工厂方法
return new Person(name, 0)
}
}

2.6.2 继承与重写

class Animal {
name: string

constructor(name: string) {
this.name = name
}

speak(): string {
return `${this.name}发出声音`
}
}

class Dog extends Animal {
override speak(): string { // override 关键字
return `${this.name}汪汪叫`
}
}

const dog = new Dog('旺财')
console.log(dog.speak()) // 旺财汪汪叫

⚠️ ArkTS 中重写父类方法建议使用 override 关键字,增强可读性与类型检查。

2.7 接口

2.7.1 接口定义与实现

interface Printable {
print(): void
}

interface Loggable {
log(message: string): void
}

// 类实现多个接口
class Document implements Printable, Loggable {
print(): void {
console.log('打印文档')
}

log(message: string): void {
console.log(message)
}
}

2.7.2 接口扩展

interface Base {
id: number
}

interface Extended extends Base {
name: string
}

const obj: Extended = { id: 1, name: 'test' }

2.8 泛型

// 泛型函数
function identity<T>(arg: T): T {
return arg
}
const str = identity<string>('hello')

// 泛型接口
interface Pair<K, V> {
key: K
value: V
}
const pair: Pair<string, number> = { key: 'age', value: 25 }

// 泛型约束
interface HasLength {
length: number
}
function logLength<T extends HasLength>(arg: T): void {
console.log(arg.length)
}

💡 泛型是封装通用工具函数的关键,本课程后续的数据工具类会大量使用。

2.9 控制语句

// if-else
if (age >= 18) {
console.log('成年人')
} else if (age >= 12) {
console.log('青少年')
} else {
console.log('儿童')
}

// 三元运算符
const result = score >= 60 ? '及格' : '不及格'

// switch
switch (day) {
case 'Monday':
console.log('周一')
break
default:
console.log('其他')
}

// for 循环
for (let i = 0; i < 5; i++) {
console.log(i)
}

// for...of(遍历数组)
const fruits = ['apple', 'banana']
for (const fruit of fruits) {
console.log(fruit)
}

2.10 数组方法

数组方法是 ArkTS 数据处理的核心工具,配合箭头函数使用:

const numbers = [1, 2, 3, 4, 5]

// map:映射转换
const doubled = numbers.map(n => n * 2) // [2, 4, 6, 8, 10]

// filter:条件过滤
const evens = numbers.filter(n => n % 2 === 0) // [2, 4]

// reduce:归约汇总
const sum = numbers.reduce((a, b) => a + b, 0) // 15

// find:查找首个满足条件元素
const found = numbers.find(n => n > 3) // 4

// some / every:存在性判断
const hasLarge = numbers.some(n => n > 4) // true
const allPositive = numbers.every(n => n > 0) // true

// forEach:遍历
numbers.forEach(n => console.log(n))
方法用途返回值
map每个元素转换新数组
filter筛选满足条件元素新数组
reduce累积归约单值
find查找首个匹配元素或 undefined
some任一满足boolean
every全部满足boolean

2.11 模块化

2.11.1 导出

// 导出类
export class UserService {
static getUser() { return {} }
}

// 导出接口
export interface Config {
apiUrl: string
}

// 导出常量/函数
export const DEFAULT_URL = 'https://api.example.com'
export function formatTime(t: number): string { return String(t) }

// 默认导出
export default class App {
static run() {}
}

2.11.2 导入

import App from './App'                    // 默认导入
import { UserService, Config } from './Services' // 具名导入
import * as Utils from './Utils' // 全部导入
import { DEFAULT_URL as URL } from './Constants' // 重命名导入

2.12 综合示例:学生成绩管理

对应 code/Chapter2Index.ets,综合运用接口、函数、数组方法、渲染控制:

// 定义学生接口
interface Student {
id: number
name: string
scores: number[]
}

// 计算平均分
function getAverage(scores: number[]): number {
const sum = scores.reduce((a, b) => a + b, 0)
return sum / scores.length
}

// 获取等级
function getGrade(average: number): string {
if (average >= 90) return 'A'
if (average >= 80) return 'B'
if (average >= 70) return 'C'
if (average >= 60) return 'D'
return 'F'
}

@Entry
@ComponentV2
struct Index {
students: Student[] = [
{ id: 1, name: 'Zhang San', scores: [90, 85, 92] },
{ id: 2, name: 'Li Si', scores: [78, 82, 88] },
{ id: 3, name: 'Wang Wu', scores: [95, 92, 98] }
]

build() {
Column({ space: 20 }) {
Column({ space: 12 }) {
Text('ArkTS Basic Syntax')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Text('函数 · 数组 · 类型')
.fontSize(14)
.fontColor('#999999')
}
.width('100%')

// 使用 map/filter/reduce 展示学生成绩
ForEach(this.students, (student: Student) => {
Row() {
Column({ space: 4 }) {
Text(student.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(`ID: ${student.id}`)
.fontSize(12)
.fontColor('#666666')
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)

Column({ space: 4 }) {
Text(`Avg: ${getAverage(student.scores).toFixed(1)}`)
.fontSize(14)
Text(`Grade: ${getGrade(getAverage(student.scores))}`)
.fontSize(14)
.fontColor('#007DFF')
}
.alignItems(HorizontalAlign.End)
}
.width('100%')
.padding(12)
.backgroundColor(Color.White)
.borderRadius(8)
})
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#f5f5f5')
}
}

运行效果(模拟器/Previewer):

  • 页面展示 3 名学生卡片
  • 每张卡片显示:姓名、ID、平均分(保留1位小数)、成绩等级
  • 数据全部来自 students 数组,通过 ForEach 渲染

运行效果截图:

Chapter2 学生成绩管理器总览

学生卡片:张三

学生卡片:王五

学生卡片:李四

💡 本章代码虽然简单,但完整体现了 ArkTS 的接口、函数、数组方法与 ArkUI 渲染控制的结合。

2.13 常见问题

Q:letconst 如何选择?

  • 优先 const,变量不会重新赋值时使用
  • 需要重新赋值时使用 let
  • 禁止使用 var(存在作用域问题)

Q:箭头函数和普通函数的区别?

  • 箭头函数没有自己的 this,继承外层作用域
  • 箭头函数不能作为构造函数
  • 在回调(如 onClick)中推荐箭头函数

Q:什么时候用 interface 而不是 class

  • 仅描述数据结构 → 用 interface
  • 需要方法逻辑/状态管理装饰器 → 用 class(后续状态管理章节会用到)

Q:数组可以存不同类型吗?

  • 可以,用联合类型:(string | number)[]
  • 但业务上建议保持同质,便于处理

2.14 本章小结

知识点掌握程度
基础/复合类型✅ 熟练
变量声明与类型安全✅ 熟练
函数与参数处理✅ 熟练
类、接口、泛型✅ 熟练
数组方法与控制流✅ 熟练
模块化导入导出✅ 了解

2.15 课后练习

  1. 定义 Product 接口(名称、价格、库存),创建商品数组
  2. 编写函数计算购物车总价(reduce 实现)
  3. 使用 filter 筛选库存大于 0 的商品
  4. 用泛型封装一个数组取最大值工具函数
  5. 将练习 1-3 集成到 Chapter2/Index.ets 的 UI 中展示

2.16 参考资料

评论

加载中…
加载中...