变量
变量用于表示程序中的数据。TypeScript 中的变量遵循如下语法规则:
- 变量名可以包含数字和字母
- 除了下划线
_和美元符号$外,不能包含其他特殊字符,如空格 - 变量名不能以数字开头
声明
需要先声明一个变量,才可以使用它。在 TypeScript 中,我们有三个关键词可以用于声明变量,分别是 var、let、const。我们先以 var 为例来介绍声明变量的几种写法,再来介绍这三个关键字之间的差异。
- 声明变量名、变量类型和初始值,这是最全的一种声明方式
var [变量名]: [变量类型] = 初始值;
// Eg
var username: string = "Owen";
TypeScript 声明变量类型的方式和 Kotlin 相同,在变量名后面加 : 变量类型。
- 申明变量名和类型,没有初始值,这时候变量的值为
undefined。
var [变量名]: [变量类型];
// Eg
var username: string;
console.log(username); // 输出 undefined,TypeScript 编译器会提示一个错误信息:在赋值前使用了变量“username”。
- 声明变量名和初始值,不显式指定类型,编译器会根据初始值智能推断变量的类型。
var [变量名] = 初始值;
// Eg
var lastname = "Lee";
lastname = 1; // 报错:不能将类型“number”分配给类型“string”。
- 只声明变量名,不指定类型和初始值,此时编译器只能推断出该变量类型为
any。
var [变量名];
// Eg
var lastname; // 类型为 any
lastname.canBeExist(); // 编译器不会对 any 类型调用的方法做类型检查
var、let 和 const
var
var 是最常使用的声明变量的关键字,但它的规则却有一点奇怪,不了解的情况下有可能踩坑。
var 声明的变量可以在包含它的函数、模块、命名空间或全局作用域内部任何位置被访问,包含它的代码块对此没有限制作用。这个特性被称为 var 作用域 或 函数作用域。
举个例子:
function f(shouldInitialize: boolean) {
if (shouldInitialize) {
var x = 10;
}
return x;
}
f(true); // returns '10'
f(false); // returns 'undefined'
变量 x 声明在 if 语句中,却可以在语句外访问它。
这样的作用域规则可能会引发一些错误,比如,多次声明同一个变量不会报错:
function sumMatrix(matrix: number[][]) {
var sum = 0;
for (var i = 0; i < matrix.length; i++) {
var currentRow = matrix[i];
for (var i = 0; i < currentRow.length; i++) {
sum += currentRow[i];
}
}
return sum;
}
这个例子中,外层循环和里层循环都定义了变量 i,里层会覆盖外层的变量 i,因为所有的 i 都引用相同的函数作用域内的变量。这些问题很容易在 Code Review 中被忽略,引起 Bug。
除此之外,var 在变量获取时也有一些奇怪之处,这里不赘述。
let
正是因为 var 奇怪的规则以及可能引起的一些问题,才引入了 let 这个关键字。let 用来声明变量的语法和 var 一致。
let [变量名]: [变量类型] = 初始值;
// Eg
let username: string = "Owen";
let 和 var 的区别在于语义。当使用 let 声明一个变量,它使用的是 词法作用域 或 块作用域。不像 var 声明的变量可以再包含它们的函数外访问,let 声明的变量在包含它们的块之外是不能访问的,这和其他编程语言变量的作用域类似。
function f(input: boolean) {
let a = 100;
if (input) {
// Still okay to reference 'a'
let b = a + 1;
return b;
}
// Error: 'b' doesn't exist here
return b;
}
上面这个例子中,变量 a 的作用域是整个函数体,变量 b 的作用域是 if 语句内部,在 if 语句外就无法访问 b。
const
const 关键字用来声明不可变的变量,它一旦赋值后就不能再改变,这里不能改变指的是引用不能变。const 的作用域和 let 一样。
const username: string = "owen";
username = "sam"; // Error
const person = {
firstname: "owen",
lastname: "lee";
}
person = {
firstname: "sam",
lastname: "liu"
}; // Error
// 但 const 变量内部的状态是可以改变的
person.firstname = "sam"; // OK
person.lastname = "liu"; // OK
推荐使用 let 代替 var,避免一些代码上的潜在风险,并且尽可能使用 const 来声明不可变变量,防止变量被随意赋值。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情