惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Schneier on Security
Schneier on Security
C
Cisco Blogs
Help Net Security
Help Net Security
I
Intezer
Simon Willison's Weblog
Simon Willison's Weblog
Know Your Adversary
Know Your Adversary
Hacker News: Ask HN
Hacker News: Ask HN
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
WordPress大学
WordPress大学
小众软件
小众软件
Jina AI
Jina AI
量子位
T
Threatpost
Forbes - Security
Forbes - Security
L
LINUX DO - 最新话题
S
Securelist
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
C
Cyber Attacks, Cyber Crime and Cyber Security
有赞技术团队
有赞技术团队
博客园_首页
T
Threat Research - Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
The Exploit Database - CXSecurity.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Scott Helme
Scott Helme
博客园 - 【当耐特】
IT之家
IT之家
Hugging Face - Blog
Hugging Face - Blog
月光博客
月光博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
大猫的无限游戏
大猫的无限游戏
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Last Watchdog
The Last Watchdog
Attack and Defense Labs
Attack and Defense Labs
Google DeepMind News
Google DeepMind News
阮一峰的网络日志
阮一峰的网络日志
SecWiki News
SecWiki News
博客园 - 叶小钗
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
The Cloudflare Blog
S
Schneier on Security
爱范儿
爱范儿
N
News and Events Feed by Topic
NISL@THU
NISL@THU
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - thammer

03 — std::vector 进阶篇 02 — 迭代器基础 01 — std::vector 基础篇 Day 17:Promise 基础 Day 16 - 读懂 TypeScript 声明文件(.d.ts) Day 15 - ArkTS 模块系统 Day 14 - ArkTS 错误处理 Day 13 - ArkTS 类型系统进阶 Day 12 - 泛型与阶段三总结 Day 11 - Interface 与类型契约 Day 10 - 继承与多态 Day 09 - Class 基础 Day 08 - 函数进阶与阶段总结 Day 07 - 函数类型与高阶函数 Day 06 - 函数基础 Day 05 - 数组和元组深入 Day 04 - 循环与迭代 Day 03 - 条件控制 Day 02 - 运算符与表达式 Day 00 - 环境准备 C++虚函数 C++ 多继承 C++成员访问权限以及继承权限 C++ 成员初始化机制总结笔记
Day 01 - 变量与类型基础
thammer · 2026-04-02 · via 博客园 - thammer

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(故障)三个状态,并创建一个变量表示当前设备处于运行中。