Skip to content
第 3 章 前端 ⏱ 8 分钟阅读

第 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 只在 {} 内有效
TDZlet / const 初始化前不可访问
解构类型类型写在右边 {}: { x: number }

动手练习 ​

  1. 作用域实验:在 if 块内 let 一个变量,块外访问看是否报错
  2. const 可变性:const obj = {x:1},改 obj.x 看是否报错
  3. 解构重命名:用对象解构重命名 user.name 为 userName,指定类型

下一章:第 4 章:函数 →

本站基于 VitePress 构建 · 由 StackHub 团队维护