3、ArkTS语言基础(上):ArkTS语法概览、变量声明与数据类型、函数定义与箭头函数、类与接口的基本使用

3.1 ArkTS语法概览:从JavaScript到ArkTS的进化

说实话,第一次接触ArkTS的时候,我心想:「这不就是TypeScript换了个马甲吗?」

后来真在鸿蒙项目里写起来,才发现没那么简单。ArkTS是华为基于TypeScript做的一套静态类型语言,专门为鸿蒙的声明式UI框架服务。它砍掉了JS里那些动态类型的「野路子」,强制你写得更规范。

我个人习惯把ArkTS看作是「带镣铐跳舞」——限制多了,但代码质量确实上去了。你想想看,在团队协作中,类型不匹配导致的bug能少一大半。

核心要点: ArkTS是静态类型语言,所有变量、函数参数、返回值都必须声明类型。这是和普通JavaScript最大的区别。

3.2 变量声明与数据类型:别再写「let a = 1」了

嗯,这里要注意。在ArkTS里,变量声明必须带上类型注解。我见过不少从JS转过来的新手,上来就写let count = 0,然后编译器直接报错。

正确的写法是这样的:

// 基础数据类型
let count: number = 0
let name: string = '鸿蒙开发'
let isReady: boolean = true
let data: null = null
let value: undefined = undefined

// 数组类型
let list: number[] = [1, 2, 3]
let names: Array<string> = ['Alice', 'Bob']

// 联合类型
let id: number | string = 100
id = 'A001'  // 这样也可以

// 类型推断(偷懒写法)
let age = 25  // 编译器自动推断为number类型

我曾经在项目里犯过一个低级错误:把一个接口返回的status字段声明成了number,结果后端某天改成了字符串"200",整个页面白屏。从那以后,我对联合类型特别敏感——let status: number | string,稳得很。

我的建议: 能用类型推断就别手写类型,代码更简洁。但如果是函数返回值、复杂对象,一定要显式声明类型,方便别人阅读。

3.3 函数定义与箭头函数:两种写法,一个灵魂

ArkTS里的函数,说白了就两种写法:普通函数和箭头函数。但它们的区别,很多人搞不清楚。

先看普通函数:

// 普通函数声明
function add(a: number, b: number): number {
  return a + b
}

// 函数表达式
const multiply = function(a: number, b: number): number {
  return a * b
}

再看箭头函数:

// 箭头函数
const subtract = (a: number, b: number): number => {
  return a - b
}

// 单行表达式可以省略return和大括号
const double = (x: number): number => x * 2

// 无参数箭头函数
const greet = (): string => 'Hello ArkTS'

为什么会有箭头函数?我记得刚学JS那会儿,被this指向搞得晕头转向。普通函数里的this是调用时决定的,而箭头函数里的this是定义时决定的。在鸿蒙的UI回调里,箭头函数能避免很多this丢失的问题。

避坑指南: 我曾经在组件的点击事件里用了普通函数,结果this指向了全局对象,数据怎么都更新不了。换成箭头函数,问题秒解。记住:在ArkTS的UI回调中,优先使用箭头函数。

3.4 类与接口的基本使用:面向对象,但别过度设计

类在ArkTS里用得挺多的,尤其是定义数据模型和业务逻辑。接口则更像是一份「契约」,规定你的类必须长什么样。

先看接口:

// 定义接口
interface User {
  id: number
  name: string
  age?: number  // 可选属性
  readonly createdAt: Date  // 只读属性
}

// 实现接口
function printUser(user: User): void {
  console.log(`用户${user.name}的ID是${user.id}`)
}

// 使用
const user: User = {
  id: 1,
  name: '张三',
  createdAt: new Date()
}
printUser(user)

再看类:

// 定义类
class Person {
  // 属性声明
  private name: string
  protected age: number
  public readonly id: number

  // 构造函数
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
    this.id = Math.floor(Math.random() * 1000)
  }

  // 方法
  public sayHello(): string {
    return `你好,我是${this.name}`
  }

  // getter/setter
  get personName(): string {
    return this.name
  }

  set personName(newName: string) {
    if (newName.length > 0) {
      this.name = newName
    }
  }
}

// 继承
class Student extends Person {
  private grade: number

  constructor(name: string, age: number, grade: number) {
    super(name, age)  // 调用父类构造函数
    this.grade = grade
  }

  // 重写方法
  public sayHello(): string {
    return `${super.sayHello()},我在${this.grade}年级`
  }
}

// 使用
const student = new Student('李四', 18, 12)
console.log(student.sayHello())

我个人习惯是:接口定义数据结构,类定义行为逻辑。别把类写得跟接口一样全是属性没有方法,那还不如直接用对象字面量。

关键区别: 接口是「有什么」,类是「能做什么」。接口只声明属性类型,类可以包含实现逻辑。在鸿蒙开发中,数据模型用接口,业务服务用类,分工明确。

3.5 实战小技巧:类型守卫与可选链

最后分享两个我在项目中常用的技巧。

类型守卫: 当你用联合类型时,需要判断具体是哪种类型。

function processValue(value: string | number): void {
  if (typeof value === 'string') {
    console.log(value.toUpperCase())
  } else {
    console.log(value.toFixed(2))
  }
}

可选链: 避免访问深层嵌套对象时报错。

// 假设有个深层对象
const response = {
  data: {
    user: {
      address: {
        city: '北京'
      }
    }
  }
}

// 传统写法(容易报错)
// const city = response.data.user.address.city

// 可选链写法(安全)
const city = response?.data?.user?.address?.city ?? '未知'
console.log(city)  // 输出:北京

嗯,这些基础语法看着简单,但真写起来容易踩坑。我建议你每学一个知识点,都打开DevEco Studio敲一遍。代码这东西,光看是学不会的。

总结一下: ArkTS的变量要声明类型,函数优先用箭头,接口定义结构,类实现逻辑。记住这四句话,基础语法就稳了。