第 3 章:变量与常量
学习目标
- 区分 var / let / const 的作用域
- 学会类型注解与类型推断
- 理解变量提升与暂时性死区
- 避开声明相关的常见坑
一、三种声明方式
typescript
// var:函数作用域,有变量提升(几乎不用)
var a: number = 1;
// let:块级作用域,可重新赋值(优先用)
let b: number = 2;
b = 3;
// const:块级作用域,声明时必须初始化,不能重新赋值
const c: number = 4;
c = 5; // ❌ Assignment to constant variable⚠️ 坑 1:
const保证的是绑定不可变,const obj = {}之后obj.x = 1是允许的,因为对象本身可变。
typescript
const user: { name: string } = { name: 'Tom' };
user.name = 'Jerry'; // ✅ 改属性允许
user = { name: 'Bob' }; // ❌ 重新赋值不允许二、类型注解 vs 类型推断
typescript
// 显式注解:开发者写明类型
let count: number = 10;
// 推断:TS 自动推导
let name = 'Tom'; // 推断为 string
name = 123; // ❌ Type 'number' is not assignable to type 'string'什么时候需要注解?
typescript
// 1. 声明时无初始值
let result: number;
result = 1;
// 2. 函数参数(必须注解,推断不到)
function add(a: number, b: number): number {
return a + b;
}
// 3. 想让变量接受多种类型
let value: string | number = 'Tom';三、块级作用域
typescript
function test(): void {
if (true) {
let x: number = 10;
const y: number = 20;
var z: number = 30;
}
console.log(z); // ✅ var 提升到函数作用域
console.log(x); // ❌ x is not defined
}四、暂时性死区(TDZ)
typescript
console.log(x); // ❌ ReferenceError:Cannot access 'x' before initialization
let x: number = 10;⚠️ 坑 2:与
var的提升不同,let/const也有提升,但初始化前不能访问,这就是 TDZ。
五、变量遮蔽(Shadowing)
typescript
let name: string = 'outer';
function test(): void {
console.log(name); // ❌ TDZ,内部 name 覆盖了外部
let name: string = 'inner';
}
test();六、解构赋值的类型
typescript
// 数组解构
const arr: [number, string] = [1, 'Tom'];
const [num, str] = arr;
// 对象解构
const user: { id: number; name: string } = { id: 1, name: 'Tom' };
const { id, name } = user;
// 重命名
const { name: userName } = user;
// 默认值
const { age = 18 }: { age?: number } = {};⚠️ 坑 3:解构时类型必须写在右边:
const { x }: { x: number } = obj,不是const { x: number } = obj(那是重命名)。
七、全局声明
typescript
// declare 全局变量(没有 .d.ts 文件时)
declare const VERSION: string;
declare function log(msg: string): void;
console.log(VERSION); // ✅
log('hello'); // ✅八、let vs const 选择标准
| 场景 | 选择 |
|---|---|
| 不会重新赋值 | const(默认) |
| 需要重新赋值(累加、状态) | let |
| 函数参数 | 参数声明本身 |
| 循环变量 | let |
⚠️ 坑 4:默认全用
const,只在需要重新赋值时才用let,可以让代码更可预测。
九、本章小结
| 要点 | 关键 |
|---|---|
| 声明方式 | var(不用)/ let / const(默认) |
| 类型注解 | 没初始值时必须写,函数参数必须写 |
| 类型推断 | 有初始值 TS 会自动推导 |
| 块级作用域 | let / const 只在 {} 内有效 |
| TDZ | let / const 初始化前不可访问 |
| 解构类型 | 类型写在右边 {}: { x: number } |
动手练习
- 作用域实验:在
if块内let一个变量,块外访问看是否报错 - const 可变性:
const obj = {x:1},改obj.x看是否报错 - 解构重命名:用对象解构重命名
user.name为userName,指定类型
下一章:第 4 章:函数 →