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,只用 let 和 const。
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 类型
只有 true 或 false 两个值。
let isOnline: boolean = true;
let hasError: boolean = false;
与 C++ 相同:ArkTS 的 if 条件支持隐式转换,规则和 JavaScript/C++ 一致:
| 类型 | 为 false 的值 |
为 true 的值 |
|---|---|---|
number |
0 |
非零数字 |
string |
"" |
非空字符串 |
boolean |
false |
true |
| 其他 | null、undefined |
— |
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 块级作用域
let 和 const 声明的变量具有块级作用域,在 {} 内声明的变量只在该块内有效。
// 块级作用域示例
{
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(故障)三个状态,并创建一个变量表示当前设备处于运行中。

浙公网安备 33010602011771号