Day 01 - 变量与类型基础

Day 01 - 变量与类型基础

目标:掌握变量定义范式、基础类型、联合类型、枚举、数组,理解值类型与引用类型
预计时间:2-3小时


课前基础:语句与分号

语句(Statement)

语句是执行某个操作的完整指令。ArkTS 中一条语句通常占一行。

let count: number = 10; // 变量声明语句
console.log("Hello"); // 函数调用语句

对比 C++:概念相同,但 ArkTS 有自动分号插入机制。


关于分号

ArkTS 可以省略分号(有自动分号插入机制),但建议始终加上分号,避免意外错误。

// ✅ 推荐:加上分号
let count: number = 10;
let name: string = "Device";

// 也可以省略(但不推荐)
let count: number = 10
let name: string = "Device"

需要分号的场景

// 同一行多条语句必须用分号分隔
let a: number = 1;
let b: number = 2;

// 以 [ 或 ( 开头的行需要前一条语句有分号
let arr: number[] = [1, 2, 3];
[4, 5, 6].forEach(x => console.log(x)); // 如果前一行没分号会报错

本课程约定:所有代码示例都使用分号。


第一部分:变量定义范式

1.1 基本语法结构

ArkTS 定义变量的固定格式

let 变量名: 类型 = 初始值;

拆解示例

let count: number = 10;
//  ↑      ↑       ↑
//  |      |       └─ 初始值:10
//  |      └─ 类型标注:number(数字类型)
//  └─ 声明关键字:let(可变变量)

对比 C++

int count = 10;           // C++:类型在前
//  ↑    ↑
//  |    └─ 初始值
//  └─ 类型

let count: number = 10;   // ArkTS:类型在后,用冒号分隔
//      ↑       ↑
//      |       └─ 初始值
//      └─ 类型标注

1.2 声明关键字:let 和 const

// let:可变变量,可以重新赋值
let count: number = 10;
count = 20; // ✅ 可以修改

// const:常量,不能重新赋值
const MAX_SIZE: number = 100;
// MAX_SIZE = 200;  // ❌ 报错!常量不能修改

对比 C++

  • let ≈ C++ 的普通变量(非 const)
  • const ≈ C++ 的 const 变量

重要:ArkTS 没有 var,只用 letconst


1.3 类型标注的位置

ArkTS 的类型在变量名后面,用冒号分隔

let name: string = "Alice"; // 字符串类型
let age: number = 25; // 数字类型
let isActive: boolean = true; // 布尔类型

为什么这样设计?

  • 先看到变量名,再看到类型,阅读更自然
  • 类型可以省略(类型推断),但变量名必须有

1.4 类型可以省略(类型推断)

ArkTS 可以根据初始值自动推断类型

let count = 10; // 自动推断为 number
let name = "Alice"; // 自动推断为 string
let active = true; // 自动推断为 boolean

但建议显式标注,代码更清晰:

// 推荐:显式标注类型
let count: number = 10;
let name: string = "Alice";

第二部分:基础类型

2.1 number 类型

ArkTS 只有 number 一种数字类型,不分 int/float/double。

let integer: number = 10; // 整数
let floating: number = 3.14; // 浮点数
let hex: number = 0xFF; // 十六进制(255)
let binary: number = 0b1010; // 二进制(10)

底层存储number 基于 IEEE 754 双精度浮点数(double),固定占用 8 字节(64位)

64位 = 1位符号 + 11位指数 + 52位尾数

有效精度为 53位(52位尾数 + 最高位隐含的1),换算成十进制约 15~16 位有效数字。

// 超出53位精度会丢失精度
let n: number = 9007199254740993; // 2^53 + 1,精度丢失
console.log(n); // 9007199254740992(错误!)

大整数使用 bigint:当数值超出 53 位精度范围时,使用 bigint 类型,数字后加 n

let big: bigint = 9007199254740993n; // ✅ 精确

对比 C++

int a = 10;         // C++:4字节整数
float b = 3.14f;    // C++:4字节单精度
double c = 3.14;    // C++:8字节双精度

let a: number = 10;     // ArkTS:统一用 number(等价于 C++ double)
let b: number = 3.14;   // ArkTS:统一用 number

2.2 string 类型

字符串用单引号、双引号或反引号,单引号和双引号完全等价

let s1: string = 'Hello'; // 单引号
let s2: string = "World"; // 双引号,与单引号等价

// 反引号:模板字符串,支持嵌入变量和多行
let deviceId: number = 1001;
let message: string = `设备ID: ${deviceId}`; // "设备ID: 1001"

// 反引号支持多行字符串
let multiLine: string = `第一行
第二行
第三行`;

${} 只能在反引号中使用,单/双引号内无效:

let id: number = 1;
let s: string = "设备: ${id}"; // ❌ 输出字面量 "设备: ${id}",不会替换
let s: string = `设备: ${id}`; // ✅ 输出 "设备: 1"

string 是值类型(与 C++ std::string 不同):

let a: string = "abc";
let b = a; // b 得到 "abc" 的副本
b = "xyz";
console.log(a); // "abc"(a 不受影响)

虽然 string 支持 str[0] 的索引访问语法,但它是基础类型,不是字符数组

对比 C++

std::string msg = "Device: " + std::to_string(id);  // C++ 繁琐

let msg: string = `Device: ${id}`;                   // ArkTS 简洁

2.3 boolean 类型

只有 truefalse 两个值。

let isOnline: boolean = true;
let hasError: boolean = false;

与 C++ 相同:ArkTS 的 if 条件支持隐式转换,规则和 JavaScript/C++ 一致:

类型 false 的值 true 的值
number 0 非零数字
string "" 非空字符串
boolean false true
其他 nullundefined
let count: number = 1;

if (count) { // ✅ 支持,count 非零为 true
  console.log("ok");
}

if (count > 0) { // ✅ 也可以显式比较,更清晰
  console.log("ok");
}

let name: string = "";
if (name) { // false,空字符串
  console.log("有名字");
}

2.4 void 类型

void 表示没有返回值,用于函数声明:

function logMessage(msg: string): void {
  console.log(msg);
  // 没有 return 语句
}

对比 C++:和 C++ 的 void 完全相同。


2.5 Object 类型

Object 是所有引用类型的基类(包括数组、自定义对象等)。很少直接使用,因为缺乏类型信息:

// ❌ 不推荐:失去类型检查
let obj: Object = [1, 2, 3];

// ✅ 推荐:使用具体类型
let arr: number[] = [1, 2, 3];

Object 的实际使用场景(配合 interface 定义对象类型)将在 Day 06 详细介绍。


第三部分:联合类型与枚举

3.1 联合类型(Union Types)

联合类型允许一个变量是多种类型之一,使用 | 符号连接。

// 定义一个可以是 string 或 number 的变量
let value: string | number;

value = "hello"; // ✓ 合法
value = 100; // ✓ 合法
// value = true;  // ✗ 报错,boolean 不在联合类型中

对比 C++

C++ 的 union 是内存共享的底层结构:

union Data {
    int i;
    float f;
};
// 所有成员共享同一块内存,同时只能存一个值

ArkTS 的联合类型是类型系统的概念,不涉及内存共享,编译器会进行类型检查:

let data: string | number;
// 类型检查确保只能赋值为 string 或 number

实际应用场景

// 函数参数可以是多种类型
function printId(id: string | number): void {
  console.log(`ID: ${id}`);
}

printId("abc123"); // ✓
printId(10086); // ✓

// 使用时需要类型守卫
function process(value: string | number): void {
  if (typeof value === "string") {
    console.log("字符串长度:", value.length);
  } else {
    console.log("数字平方:", value * value);
  }
}

3.2 枚举(Enum)

枚举是一组具名常量的集合,用于表示一组相关的离散值。

// 定义方向枚举
enum Direction {
UP, // 默认值为 0
DOWN, // 默认值为 1
LEFT, // 默认值为 2
RIGHT // 默认值为 3
}

let dir: Direction = Direction.UP;
console.log(dir); // 输出: 0
console.log(Direction[0]); // 输出: "UP" (反向映射)

自定义枚举值

// 自定义数值
enum StatusCode {
OK = 200,
NOT_FOUND = 404,
ERROR = 500
}

// 字符串枚举
enum Color {
RED = "#FF0000",
GREEN = "#00FF00",
BLUE = "#0000FF"
}

let status: StatusCode = StatusCode.OK;
console.log(status); // 200

let color: Color = Color.RED;
console.log(color); // "#FF0000"

对比 C++

特性 C/C++ 枚举 ArkTS 枚举
底层类型 整数 支持数字和字符串
反向映射 不支持 数字枚举支持
使用场景 整数常量替代 类型安全的配置选项

枚举的实际应用

// 设备状态枚举
enum DeviceState {
OFFLINE = 0,
CONNECTING = 1,
ONLINE = 2,
ERROR = 3
}

function getStateText(state: DeviceState): string {
  switch (state) {
    case DeviceState.OFFLINE:
      return "离线";
    case DeviceState.CONNECTING:
      return "连接中";
    case DeviceState.ONLINE:
      return "在线";
    case DeviceState.ERROR:
      return "故障";
    default:
      return "未知";
  }
}

let currentState: DeviceState = DeviceState.ONLINE;
console.log(getStateText(currentState)); // "在线"

第四部分:数组(第一个引用类型)

4.1 数组声明

// 语法:类型[]
let numbers: number[] = [1, 2, 3, 4, 5];
let names: string[] = ["Alice", "Bob", "Charlie"];

// 空数组(必须指定类型)
let empty: number[] = [];

对比 C++

std::vector<int> numbers = {1, 2, 3, 4, 5};  // C++

let numbers: number[] = [1, 2, 3, 4, 5];      // ArkTS

4.2 数组操作

let arr: number[] = [10, 20, 30];

// 访问元素(0-based)
let first: number = arr[0]; // 10

// 修改元素
arr[1] = 25; // [10, 25, 30]

// 常用方法
arr.push(40); // 末尾添加 [10, 25, 30, 40]
arr.pop(); // 删除末尾,返回40
arr.length; // 获取长度(3)

第五部分:值类型 vs 引用类型

5.1 核心区别

特性 基础类型(值类型) 引用类型
包含类型 number, string, boolean Array, Object
变量存储 直接存储值 存储内存地址
赋值行为 复制值 复制地址

5.2 赋值对比

基础类型(复制值)

let a: number = 10;
let b = a; // b 得到 10 的副本

b = 20;
console.log(a); // 10(a 不变)
console.log(b); // 20

引用类型(复制地址)

let arr1: number[] = [1, 2, 3];
let arr2 = arr1; // arr2 得到相同的内存地址

arr2[0] = 100;
console.log(arr1[0]); // 100(arr1 也变了!)
console.log(arr2[0]); // 100

5.3 如何复制数组(创建副本)

let arr1: number[] = [1, 2, 3];

// 使用展开运算符创建新数组
let arr2 = [...arr1];

arr2[0] = 100;
console.log(arr1[0]); // 1(没变)
console.log(arr2[0]); // 100

第六部分:作用域

6.1 块级作用域

letconst 声明的变量具有块级作用域,在 {} 内声明的变量只在该块内有效。

// 块级作用域示例
{
  let blockVar: number = 10;
  console.log(blockVar); // 10
}
// console.log(blockVar);  // ❌ 错误:blockVar 在这里不可访问

// if 语句块
let temperature: number = 85;
if (temperature > 80) {
  let warning: string = "温度过高";
  console.log(warning);
}
// console.log(warning);  // ❌ 错误:warning 只在 if 块内有效

对比 C++:C++ 也是块级作用域,概念相同。


6.2 函数作用域

函数参数和内部声明的变量只在函数内有效:

function controlDevice(deviceId: number, command: string): void {
  // deviceId 和 command 只在函数内有效
  let result: string = `${deviceId}: ${command}`;
  console.log(result);
}

// console.log(deviceId);  // ❌ 错误:deviceId 未定义

6.3 变量遮蔽(Shadowing)

内层作用域可以声明与外层同名的变量,这会"遮蔽"外层变量:

let deviceName: string = "全局设备";

function setupDevice(): void {
  let deviceName: string = "局部设备"; // 遮蔽全局变量
  console.log(deviceName); // "局部设备"

  if (true) {
    let deviceName: string = "块级设备"; // 再次遮蔽
    console.log(deviceName); // "块级设备"
  }

  console.log(deviceName); // "局部设备"(恢复)
}

console.log(deviceName); // "全局设备"

测试题

题1:以下代码的每一部分分别是什么?

let temperature: number = 36.5;
  • let 是______
  • temperature 是______
  • : number 是______
  • 36.5 是______

题2:以下哪个是正确的?

A. let x: int = 10;
B. let y: number = 3.14;
C. let flag: boolean = 1;
D. const MAX: number = 100; MAX = 200;

题3:以下代码输出什么?为什么?

let x: number = 10;
let y = x;
y = 20;
console.log(x);

let arr1: number[] = [1, 2, 3];
let arr2 = arr1;
arr2[0] = 100;
console.log(arr1[0]);

题4:如何创建数组的独立副本?写出代码。

题5:以下代码输出什么?

let x: number = 10;

function test(): void {
  let x: number = 20;
  console.log(x);
}

test();
console.log(x);

题6:用索引访问获取数组的前两个元素并打印:

let coords: number[] = [100, 200, 300];
// 你的代码
// console.log(x); // 100
// console.log(y); // 200

题7:以下联合类型的定义正确吗?如果正确,value 可以赋什么值?

let value: string | number | boolean;

题8:定义一个表示设备状态的枚举 DeviceStatus,包含 STANDBY(待机)、RUNNING(运行中)、FAULT(故障)三个状态,并创建一个变量表示当前设备处于运行中。

posted @ 2026-04-02 17:07  thammer  阅读(2)  评论(0)    收藏  举报