鸿蒙开发之:ArkTS语言基础入门

63 阅读6分钟

本文字数:2560字 | 预计阅读时间:10分钟

适用人群:有JavaScript/TypeScript基础、Java/Kotlin开发者、零基础但想系统学习鸿蒙开发

前置知识:建议先阅读本系列第1篇《环境搭建与第一个应用》

系列导航:本文是《鸿蒙开发系列》第2篇,下篇将深入讲解ArkUI组件布局

一、ArkTS初探:鸿蒙的专属开发语言

1.1 什么是ArkTS?

ArkTS是鸿蒙生态的应用开发语言,它基于TypeScript(简称TS)扩展,并针对鸿蒙系统的特性进行了深度优化。如果你熟悉TypeScript,那么学习ArkTS将事半功倍。

1.2 为什么选择ArkTS而不是其他语言?

语言优点在鸿蒙中的定位
ArkTS类型安全、性能优化、鸿蒙原生支持主推语言,全场景应用开发
JavaScript灵活、生态丰富兼容运行,但性能不如ArkTS
Java成熟、稳定主要用于系统服务和底层开发
C/C++高性能、底层控制驱动开发、高性能计算

1.3 ArkTS与TypeScript的核心差异

typescript

复制下载

// TypeScript中的类
class Person {
  name: string;
  age: number;
  
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

// ArkTS中的增强(增加了装饰器支持)
@Component
struct PersonComponent {
  @State name: string = '';
  @State age: number = 0;
  
  // 更多鸿蒙特有的装饰器和API
}

二、基础类型系统:让代码更安全

2.1 基本数据类型

ArkTS继承了TypeScript的类型系统,并做了一些扩展:

typescript

复制下载

// 1. 数值类型 - 支持整数和浮点数
let decimal: number = 6;
let hex: number = 0xf00d;      // 十六进制
let binary: number = 0b1010;   // 二进制
let octal: number = 0o744;     // 八进制
let float: number = 3.14;

// 2. 字符串类型 - 三种定义方式
let name1: string = "张三";
let name2: string = '李四';
let template: string = `我的名字是${name1},年龄${decimal}岁`;

// 3. 布尔类型
let isDone: boolean = false;
let isHarmony: boolean = true;

// 4. 数组类型 - 两种声明方式
let list1: number[] = [1, 2, 3];
let list2: Array<string> = ['a', 'b', 'c'];

// 5. 元组类型 - 固定长度的数组
let tuple: [string, number, boolean];
tuple = ['鸿蒙', 4.0, true];  // 正确
// tuple = [4.0, '鸿蒙', true];  // 错误:类型不匹配

2.2 特殊类型

typescript

复制下载

// 1. Any类型 - 任意类型(慎用,会失去类型检查)
let notSure: any = 4;
notSure = "可能是字符串";
notSure = false;  // 也可以赋值为布尔值

// 2. Unknown类型 - 更安全的Any
let value: unknown;
value = 'Hello';
value = 42;
// let str: string = value;  // 错误:需要类型断言
let str: string = value as string;  // 正确:使用类型断言

// 3. Void类型 - 没有返回值
function warnUser(): void {
  console.log("这是一个警告");
}

// 4. Null和Undefined
let u: undefined = undefined;
let n: null = null;

// 5. Never类型 - 永远不会发生的类型
function error(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {}
}

三、变量声明与作用域

3.1 三种声明方式对比

typescript

复制下载

// 1. var - 函数作用域(不推荐在ArkTS中使用)
function varTest() {
  var x = 10;
  if (true) {
    var x = 20;  // 同一个变量!
    console.log(x);  // 20
  }
  console.log(x);  // 20
}

// 2. let - 块级作用域(推荐)
function letTest() {
  let x = 10;
  if (true) {
    let x = 20;  // 不同的变量
    console.log(x);  // 20
  }
  console.log(x);  // 10
}

// 3. const - 常量(不可重新赋值)
const PI = 3.14159;
// PI = 3.14;  // 错误:常量不能重新赋值

const person = { name: '张三' };
person.name = '李四';  // 正确:对象的属性可以修改
// person = { name: '王五' };  // 错误:不能重新赋值

3.2 类型注解与类型推断

typescript

复制下载

// 显式类型注解
let userName: string = "鸿蒙开发者";
let userAge: number = 25;
let isDeveloper: boolean = true;

// 类型推断 - TypeScript/ArkTS会自动推断类型
let company = "华为";      // 推断为string
let version = 4.0;         // 推断为number
let released = true;       // 推断为boolean

// 联合类型
let id: string | number;
id = "ABC123";    // 正确
id = 123456;      // 正确
// id = true;     // 错误:只能是string或number

// 类型别名
type UserID = string | number;
type Callback = (data: string) => void;

let userId: UserID = "user_001";
let onSuccess: Callback = (result) => {
  console.log(`结果:${result}`);
};

四、函数:ArkTS的核心构建块

4.1 函数定义与调用

typescript

复制下载

// 1. 命名函数
function add(x: number, y: number): number {
  return x + y;
}

// 2. 函数表达式
const multiply = function(x: number, y: number): number {
  return x * y;
};

// 3. 箭头函数(推荐)
const divide = (x: number, y: number): number => {
  return x / y;
};

// 4. 简写箭头函数
const square = (x: number): number => x * x;

// 调用函数
console.log(add(5, 3));        // 8
console.log(multiply(4, 6));   // 24
console.log(divide(10, 2));    // 5
console.log(square(9));        // 81

4.2 函数参数高级特性

typescript

复制下载

// 1. 可选参数
function buildName(firstName: string, lastName?: string) {
  return lastName ? `${firstName} ${lastName}` : firstName;
}
console.log(buildName("张"));           // 张
console.log(buildName("张", "三"));     // 张三

// 2. 默认参数
function createDevice(name: string, type: string = "手机") {
  return `${name} - ${type}`;
}
console.log(createDevice("Mate60"));          // Mate60 - 手机
console.log(createDevice("Watch4", "手表"));  // Watch4 - 手表

// 3. 剩余参数
function sum(...numbers: number[]): number {
  return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3));        // 6
console.log(sum(1, 2, 3, 4, 5));  // 15

// 4. 函数重载
function format(input: string): string;
function format(input: number): string;
function format(input: string | number): string {
  if (typeof input === 'string') {
    return `字符串: ${input}`;
  } else {
    return `数字: ${input}`;
  }
}
console.log(format("鸿蒙"));   // 字符串: 鸿蒙
console.log.format(4.0);       // 数字: 4.0

五、类与面向对象编程

5.1 类的定义与使用

typescript

复制下载

// 基础类定义
class Device {
  // 属性
  name: string;
  type: string;
  private serialNumber: string;  // 私有属性
  
  // 构造函数
  constructor(name: string, type: string, serial: string) {
    this.name = name;
    this.type = type;
    this.serialNumber = serial;
  }
  
  // 方法
  getInfo(): string {
    return `${this.name} (${this.type})`;
  }
  
  // 私有方法
  private getSerial(): string {
    return this.serialNumber;
  }
  
  // 静态方法
  static createDefault(): Device {
    return new Device("默认设备", "未知", "000000");
  }
}

// 创建实例
const phone = new Device("华为手机", "智能手机", "SN123456");
console.log(phone.getInfo());  // 华为手机 (智能手机)
// console.log(phone.serialNumber);  // 错误:私有属性不能访问

// 调用静态方法
const defaultDevice = Device.createDefault();

5.2 继承与多态

typescript

复制下载

// 基类
class Animal {
  name: string;
  
  constructor(name: string) {
    this.name = name;
  }
  
  makeSound(): string {
    return "动物叫声";
  }
}

// 派生类
class Dog extends Animal {
  breed: string;
  
  constructor(name: string, breed: string) {
    super(name);  // 调用父类构造函数
    this.breed = breed;
  }
  
  // 重写父类方法
  makeSound(): string {
    return "汪汪汪";
  }
  
  // 新增方法
  fetch(): string {
    return `${this.name} 去捡球了`;
  }
}

// 使用
const myDog = new Dog("旺财", "金毛");
console.log(myDog.makeSound());  // 汪汪汪
console.log(myDog.fetch());      // 旺财 去捡球了

5.3 抽象类与接口

typescript

复制下载

// 接口定义
interface USBDevice {
  readonly version: string;  // 只读属性
  connect(): boolean;
  disconnect(): void;
}

// 抽象类
abstract class StorageDevice {
  abstract capacity: number;
  
  abstract readData(): string;
  
  abstract writeData(data: string): void;
  
  // 可以有具体实现的方法
  getInfo(): string {
    return `存储设备,容量: ${this.capacity}GB`;
  }
}

// 实现接口和继承抽象类
class USBFlashDrive extends StorageDevice implements USBDevice {
  capacity: number;
  readonly version: string = "3.0";
  
  constructor(capacity: number) {
    super();
    this.capacity = capacity;
  }
  
  connect(): boolean {
    console.log("USB设备已连接");
    return true;
  }
  
  disconnect(): void {
    console.log("USB设备已断开");
  }
  
  readData(): string {
    return "从USB读取数据";
  }
  
  writeData(data: string): void {
    console.log(`写入数据: ${data}`);
  }
}

// 使用
const flashDrive = new USBFlashDrive(64);
flashDrive.connect();
console.log(flashDrive.getInfo());

六、装饰器:ArkTS的魔法特性

6.1 内置装饰器

typescript

复制下载

// 1. @Entry - 页面入口装饰器
@Entry
@Component
struct IndexPage {
  // 2. @State - 状态装饰器
  @State count: number = 0;
  @State message: string = 'Hello';
  
  // 3. @Prop - 父子组件传值
  @Prop title: string = '默认标题';
  
  // 4. @Link - 双向数据绑定
  @Link isActive: boolean;
  
  // 5. @Watch - 监听状态变化
  @Watch('onCountChange')
  @State watchedCount: number = 0;
  
  onCountChange(): void {
    console.log(`计数变化: ${this.watchedCount}`);
  }
  
  // 构建函数
  build() {
    // UI构建代码
  }
}

// 6. 自定义装饰器
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  
  descriptor.value = function(...args: any[]) {
    console.log(`调用方法: ${propertyKey}`);
    console.log(`参数: ${JSON.stringify(args)}`);
    const result = originalMethod.apply(this, args);
    console.log(`返回值: ${result}`);
    return result;
  };
  
  return descriptor;
}

class Calculator {
  @log
  add(x: number, y: number): number {
    return x + y;
  }
}

七、模块化与代码组织

7.1 导出与导入

typescript

复制下载

// user.ts - 导出模块
export interface User {
  id: number;
  name: string;
  age: number;
}

export class UserService {
  static getUser(id: number): User {
    return { id, name: "测试用户", age: 25 };
  }
}

// 默认导出
export default class Logger {
  static log(message: string): void {
    console.log(`[LOG] ${message}`);
  }
}

// main.ts - 导入模块
import Logger from './user';  // 默认导入
import { User, UserService } from './user';  // 命名导入

// 使用
const user: User = UserService.getUser(1);
Logger.log(`用户: ${user.name}`);

7.2 命名空间

typescript

复制下载

// 定义命名空间
namespace HarmonyUtils {
  export function formatDate(date: Date): string {
    return date.toLocaleDateString();
  }
  
  export namespace Validators {
    export function isEmail(email: string): boolean {
      return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(email);
    }
  }
}

// 使用
console.log(HarmonyUtils.formatDate(new Date()));
console.log(HarmonyUtils.Validators.isEmail("test@huawei.com"));

八、实战示例:用户管理系统

typescript

复制下载

// 定义用户类型
type Gender = 'male' | 'female' | 'other';

interface IUser {
  id: string;
  name: string;
  age: number;
  gender: Gender;
  email: string;
}

// 用户类
class User implements IUser {
  constructor(
    public id: string,
    public name: string,
    public age: number,
    public gender: Gender,
    public email: string
  ) {}
  
  // 获取用户信息
  getInfo(): string {
    return `${this.name} (${this.age}岁, ${this.gender})`;
  }
  
  // 验证邮箱
  isValidEmail(): boolean {
    return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(this.email);
  }
}

// 用户管理类
class UserManager {
  private users: Map<string, User> = new Map();
  
  // 添加用户
  addUser(user: User): boolean {
    if (this.users.has(user.id)) {
      return false;
    }
    if (!user.isValidEmail()) {
      console.error('邮箱格式不正确');
      return false;
    }
    this.users.set(user.id, user);
    return true;
  }
  
  // 获取用户
  getUser(id: string): User | undefined {
    return this.users.get(id);
  }
  
  // 获取所有用户
  getAllUsers(): User[] {
    return Array.from(this.users.values());
  }
  
  // 筛选用户
  filterUsers(predicate: (user: User) => boolean): User[] {
    return this.getAllUsers().filter(predicate);
  }
}

// 使用示例
const userManager = new UserManager();

// 创建用户
const user1 = new User('001', '张三', 25, 'male', 'zhangsan@huawei.com');
const user2 = new User('002', '李四', 30, 'female', 'lisi@harmonyos.com');

// 添加用户
userManager.addUser(user1);
userManager.addUser(user2);

// 查询用户
console.log(userManager.getUser('001')?.getInfo());  // 张三 (25岁, male)

// 筛选成年用户
const adults = userManager.filterUsers(user => user.age >= 18);
console.log(`成年用户数量: ${adults.length}`);

九、最佳实践与常见错误

9.1 最佳实践

typescript

复制下载

// 1. 始终使用严格模式
// 在tsconfig.json中配置
{
  "compilerOptions": {
    "strict": true
  }
}

// 2. 优先使用const,其次是let,避免var
const APP_NAME = '鸿蒙应用';
let isLoading = false;

// 3. 明确函数返回值类型
function calculateTotal(price: number, quantity: number): number {
  return price * quantity;
}

// 4. 使用接口定义复杂对象结构
interface AppConfig {
  name: string;
  version: string;
  apiUrl: string;
  timeout?: number;  // 可选属性
}

// 5. 合理使用类型断言
const element = document.getElementById('root') as HTMLDivElement;

9.2 常见错误及解决

typescript

复制下载

// 错误1:类型不匹配
let count: number = 10;
// count = "20";  // 错误:不能将字符串赋值给数值类型

// 错误2:访问不存在的属性
interface Product {
  name: string;
  price: number;
}

const product: Product = { name: "手机", price: 3999 };
// console.log(product.discount);  // 错误:discount不存在

// 错误3:未处理可选参数
function greet(name?: string) {
  // console.log(`Hello, ${name.toUpperCase()}`);  // 错误:name可能为undefined
  console.log(`Hello, ${name?.toUpperCase()}`);  // 正确:使用可选链
}

// 错误4:错误的类型断言
const data: any = "这是一个字符串";
// const length: number = (data as number).length;  // 运行时错误
const length: number = (data as string).length;  // 正确

十、学习资源与下期预告

10.1 官方学习资源

10.2 实践建议

  1. 每天练习:至少写30分钟ArkTS代码
  2. 项目驱动:尝试用ArkTS实现一个小工具
  3. 阅读源码:学习鸿蒙官方示例项目
  4. 参与社区:在华为开发者论坛提问和解答

10.3 下期预告:《鸿蒙开发之:ArkUI组件布局全解析》

下篇文章将深入讲解:

  • 常用UI组件:Text、Button、Image、Input等
  • 六大布局方式:Flex、Column、Row、Stack、Grid、List
  • 组件样式与主题配置
  • 实战:构建一个完整的用户界面 可以加入班级学习鸿蒙了:developer.huawei.com/consumer/cn…