Skip to content

TypeScript 变量声明

在 TypeScript 中,变量声明是编程的基础。TypeScript 支持三种变量声明方式:varletconst。本文将详细介绍这些变量声明方式的使用方法和区别。

1. var 声明

var 是 JavaScript 中传统的变量声明方式,它具有函数作用域。

基本用法

typescript
var name: string = "John";
var age: number = 30;
var isStudent: boolean = true;

函数作用域

var 声明的变量具有函数作用域,这意味着变量在声明它的函数内部都可以访问,无论声明在函数的哪个位置。

typescript
function test() {
  console.log(x); // undefined(变量提升)
  var x: number = 10;
  console.log(x); // 10
  
  if (true) {
    var x: number = 20; // 同一个变量
    console.log(x); // 20
  }
  
  console.log(x); // 20(if 块内的赋值影响了外部的变量)
}

test();

变量提升

var 声明的变量会被提升到函数的顶部,这意味着你可以在声明变量之前使用它。

typescript
function test() {
  console.log(message); // undefined
  var message: string = "Hello";
  console.log(message); // Hello
}

test();

2. let 声明

let 是 ES6 引入的变量声明方式,它具有块级作用域。

基本用法

typescript
let name: string = "John";
let age: number = 30;
let isStudent: boolean = true;

块级作用域

let 声明的变量具有块级作用域,这意味着变量只在声明它的块(由 {} 包围的代码块)内部可以访问。

typescript
function test() {
  let x: number = 10;
  console.log(x); // 10
  
  if (true) {
    let x: number = 20; // 不同的变量
    console.log(x); // 20
  }
  
  console.log(x); // 10(if 块内的变量不影响外部的变量)
}

test();

不存在变量提升

let 声明的变量不会被提升,你不能在声明变量之前使用它。

typescript
function test() {
  // console.log(message); // 错误:在声明之前使用变量
  let message: string = "Hello";
  console.log(message); // Hello
}

test();

暂时性死区

let 声明的变量在声明之前存在一个"暂时性死区",在这个区域内,变量不可访问。

typescript
function test() {
  console.log(typeof message); // 错误:在声明之前使用变量
  let message: string = "Hello";
}

test();

3. const 声明

const 用于声明常量,一旦赋值就不能修改。它也具有块级作用域。

基本用法

typescript
const PI: number = 3.14159;
const name: string = "John";
const isStudent: boolean = true;

不能重新赋值

const 声明的变量一旦赋值就不能重新赋值。

typescript
const PI: number = 3.14159;
// PI = 3.14; // 错误:不能修改常量

块级作用域

const 声明的变量也具有块级作用域。

typescript
function test() {
  const x: number = 10;
  console.log(x); // 10
  
  if (true) {
    const x: number = 20; // 不同的变量
    console.log(x); // 20
  }
  
  console.log(x); // 10
}

test();

引用类型的 const

对于引用类型(如对象和数组),const 声明的变量不能重新赋值,但可以修改对象的属性或数组的元素。

typescript
// 对象
const person = {
  name: "John",
  age: 30
};

// 可以修改对象的属性
person.age = 31;
console.log(person.age); // 31

// 不能重新赋值整个对象
// person = { name: "Jane", age: 25 }; // 错误:不能修改常量

// 数组
const numbers = [1, 2, 3, 4, 5];

// 可以修改数组的元素
numbers[0] = 10;
console.log(numbers); // [10, 2, 3, 4, 5]

// 可以使用数组方法
numbers.push(6);
console.log(numbers); // [10, 2, 3, 4, 5, 6]

// 不能重新赋值整个数组
// numbers = [6, 7, 8, 9, 10]; // 错误:不能修改常量

4. var、let 和 const 的区别

特性varletconst
作用域函数作用域块级作用域块级作用域
变量提升
重复声明允许不允许不允许
重新赋值允许允许不允许
暂时性死区

5. 变量声明的最佳实践

1. 优先使用 const

尽可能使用 const 声明变量,只有当你需要重新赋值时才使用 let。这样可以减少变量被意外修改的风险。

typescript
// 推荐
const name: string = "John";
const age: number = 30;

// 只有当需要重新赋值时才使用 let
let count: number = 0;
count = 1;

2. 避免使用 var

尽量避免使用 var 声明变量,因为它具有函数作用域和变量提升,容易导致变量作用域混乱。

typescript
// 不推荐
var name: string = "John";

// 推荐
let name: string = "John";
const age: number = 30;

3. 明确类型标注

为变量添加明确的类型标注,提高代码的可读性和可维护性。

typescript
// 推荐
const name: string = "John";
const age: number = 30;
const isStudent: boolean = true;

// 也可以依靠类型推断
const name = "John"; // TypeScript 会推断出 name 是 string 类型
const age = 30; // TypeScript 会推断出 age 是 number 类型

4. 解构赋值

使用解构赋值可以更简洁地声明多个变量。

typescript
// 数组解构
const [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1 2 3

// 对象解构
const { name, age } = { name: "John", age: 30 };
console.log(name, age); // John 30

5. 类型别名

使用类型别名可以为复杂的类型定义一个简短的名称,提高代码的可读性。

typescript
type User = {
  name: string;
  age: number;
  email: string;
};

const user: User = {
  name: "John",
  age: 30,
  email: "john@example.com"
};

6. 变量作用域

全局作用域

在函数外部声明的变量具有全局作用域,可以在整个程序中访问。

typescript
// 全局变量
const globalVar: string = "Global";

function test() {
  console.log(globalVar); // 可以访问全局变量
}

test();
console.log(globalVar); // 可以访问全局变量

函数作用域

在函数内部声明的变量(使用 var)具有函数作用域,只能在函数内部访问。

typescript
function test() {
  var functionVar: string = "Function";
  console.log(functionVar); // 可以访问函数变量
}

test();
// console.log(functionVar); // 错误:无法访问函数变量

块级作用域

在块(由 {} 包围的代码块)内部声明的变量(使用 letconst)具有块级作用域,只能在块内部访问。

typescript
if (true) {
  let blockVar: string = "Block";
  console.log(blockVar); // 可以访问块变量
}

// console.log(blockVar); // 错误:无法访问块变量

7. 变量声明的常见错误

1. 未声明变量

在使用变量之前必须先声明它。

typescript
// 错误:未声明变量
// console.log(name);

// 正确
let name: string = "John";
console.log(name);

2. 重复声明变量

使用 letconst 不能重复声明同一个变量。

typescript
// 错误:重复声明变量
let name: string = "John";
// let name: string = "Jane";

// 正确
let name: string = "John";
name = "Jane";

3. 修改 const 变量

不能修改 const 声明的变量。

typescript
// 错误:修改 const 变量
const name: string = "John";
// name = "Jane";

// 正确
let name: string = "John";
name = "Jane";

4. 在声明之前使用 let 或 const 变量

不能在声明 letconst 变量之前使用它。

typescript
// 错误:在声明之前使用变量
// console.log(name);
let name: string = "John";

// 正确
let name: string = "John";
console.log(name);

8. 变量命名规则

在 TypeScript 中,变量命名必须遵循以下规则:

  • 只能包含字母、数字、下划线(_)和美元符号($)
  • 不能以数字开头
  • 不能使用 TypeScript 的关键字作为变量名
  • 区分大小写

命名约定

  • 驼峰命名法:变量名和函数名使用驼峰命名法,如 firstNamegetUser
  • 帕斯卡命名法:类名和接口名使用帕斯卡命名法,如 PersonUserInterface
  • 全大写:常量使用全大写,如 PIMAX_VALUE
typescript
// 驼峰命名法
let firstName: string = "John";
function getUser() { /* ... */ }

// 帕斯卡命名法
class Person { /* ... */ }
interface UserInterface { /* ... */ }

// 全大写
const PI: number = 3.14159;
const MAX_VALUE: number = 1000;

总结

TypeScript 支持三种变量声明方式:

  • var:函数作用域,存在变量提升,允许重复声明和重新赋值
  • let:块级作用域,不存在变量提升,不允许重复声明,允许重新赋值
  • const:块级作用域,不存在变量提升,不允许重复声明和重新赋值

最佳实践:

  • 优先使用 const,只有当需要重新赋值时才使用 let
  • 避免使用 var
  • 为变量添加明确的类型标注
  • 使用解构赋值和类型别名提高代码的可读性
  • 遵循命名约定

通过正确使用变量声明方式,你可以编写更安全、更可维护的 TypeScript 代码。