2.【TypeScript 教程】TypeScript 变量声明

简介: 2.【TypeScript 教程】TypeScript 变量声明

本节介绍 var let const 这三种变量的声明方式,重点讨论作用域与变量提升的相关知识点,这部分往往也是面试常考部分,需要多加注意。


说明: 在使用 TypeScript 进行变量声明时,一般建议添加对应的变量类型,由于本节是整个系列教程的第一节,还未介绍 TypeScript 的类型系统,所以本节的例子仍采用 JavaScript 的变量声明方式。虽然在变量声明时没有添加变量类型,但是 TypeScript 会自动进行类型推导,得到正确的变量类型,这个在后续章节也会专门介绍。

1. 解释

TypeScript 是 JavaScript 的超集,同 JavaScript 一样,声明变量可以采用下面三个关键字:

  • var
  • let
  • const

2. var 声明

通过 var 关键字来定义 JavaScript 变量,这个大家都能理解:

var num = 10

2.1 作用域

下面我们来讨论一个为什么尽量避免使用 var

快速的猜一下下面的代码会返回什么:

for (var i = 0; i < 10; i++) {
  setTimeout(function () {
    console.log(i)
  }, 100 * i)
}

相信很多人都踩过这个坑,这几乎是作用域的必考题目,但如果你不了解,不要担心,你并不是一个人。大多数人期望输出的结果是这样的:

0
1
2
3
4
5
6
7
8
9

然而,实际结果是这样的:

10
10
10
10
10
10
10
10
10
10

解释:这里的 i 是在全局作用域中的,只存在一个值。 setTimeout 这个异步函数在若干毫秒后执行,并且它是在 for 循环结束后的。在 for 循环结束后, i 的值为 10,所以当函数被调用的时候,它会打印出 10

下面介绍几种可以实现我们预期输出结果的方法:

通过调用函数,创建函数作用域

for (var i = 0; i < 10; i++) {
  f(i)
}
 
function f (i) {
  setTimeout(function () {
    console.log(i)
  }, 100)
}

立即执行函数,创建函数作用域

for (var i = 0; i < 10; i++) {
  (function (i) {
    setTimeout(function () {
      console.log(i)
    }, 100 * i)
  })(i)
}

2.2 变量提升

看下面的例子:

1. console.log(a) // undefined
2. var a = 1

它等价于:

var a
console.log(a) // undefined
a = 1

从上面的例子中可以看出,关键词 var 会进行变量提升。

如果把上面的 var 换成 let 呢?

console.log(a) // ReferenceError: a is not defined
let a = 1 

会报错 a is not defined 未定义,这里也可以看出 varlet 在变量提升的不同:

  • var 会将变量的创建初始化都进行提升
  • let 只会将创建提升,而初始化未被提升,称之为暂时性死区

3. let 声明

现在你已经知道了 var 存在全局作用域和变量提升的问题,这恰好说明了为什么用 let 语句来声明变量。

let num = 10

下面介绍 let 的一些特点:

3.1 块作用域

在 ES6 之前,ECMAScript 的作用域只有两种:

  • 全局作用域
  • 函数作用域

现在通过命令 let 和 const 新增了“块级作用域”,定义在代码块中的变量在代码块被执行结束后会被释放掉:

function block() {
  if (true) {
    let a = 10
    console.log(a) // 10
  }
 
  console.log(a) // Cannot find name 'a'.ts(2304)
}

代码解释:

第 3 - 4 行,a 变量在 if{} 代码块中是有效的,正常输出 10。

第7行,在 if{} 代码块外就被释放掉了,所以会报错误。

包括在一对花括号中的一组语句称之为”代码块“,它可以替换掉上面介绍 var 时使用的立即执行函数:

// 立即执行函数
(function(){
  var a = 10
}())
 
// 代码块
{
  let a = 10
}

3.2 重定义

在使用 var 声明时,不论声明几次,最终只会得到一个:

1. var x
2. var x
3. var x

这是一个完全有效的代码,所有 x 的声明其实都指向了同一个引用,但这也是很多 bug 产生的原因。 let 的声明就严格了许多:

let x
let x // Cannot redeclare block-scoped variable 'x'

4. const 声明

关键字 const 声明变量,它被赋值后不能再改变。 换句话说,它拥有与 let 相同的作用域规则,但是不能重新赋值。


用 const 声明变量,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。用 const 声明初始数据类型如布尔值、数字、字符串,可以理解为声明常量,因为这些初始类型的值就保存在变量所指向的那个内存地址。

const num = 10
const brand = 'imooc'
const registered = true
 
num = 20 // Cannot assign to 'num' because it is a constant.ts(2588)

代码解释: 第 5 行,在给 num 第二次赋值时会报错。

对于复合类型的数据来说,变量所指向的内存地址保存的只是一个指针,const 能够保证其指针不变,但属性值是可变的:

const person = {
  name: 'Tom',
  address: 'Baker Street 221b'
}
 
// error
person = {
  name: 'Sherlock',
  address: 'Baker Street 221b'
}
 
// ok
person.name = 'Sherlock'

代码解释: 第 7 行,对已经使用 const 声明的变量重新赋值报错,但是在第 13 行,只是对这个对象的属性赋值是可以的。

5. 小结

阅读本小节中三种不同的变量声明,我们知道了:

  • letcount 实现了块级作用域。
  • 所有变量除了你计划去修改的都应该使用 const
  • 尽量使用 letconst 来声明变量,减少 var 的使用。
相关文章
|
2月前
|
JavaScript 前端开发
TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第11天】TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
2月前
|
JavaScript 前端开发 Java
TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第10天】TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
2月前
|
JavaScript 前端开发 安全
TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第9天】TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
2月前
|
JavaScript 索引
TypeScript(TS)安装指南与基础教程学习全攻略(二)
TypeScript(TS)安装指南与基础教程学习全攻略(二)
59 0
|
2月前
|
JavaScript 前端开发 安全
TypeScript(TS)安装指南与基础教程学习全攻略(一)
TypeScript(TS)安装指南与基础教程学习全攻略(一)
31 0
|
4月前
|
JavaScript 前端开发 编译器
TypeScript教程(一)在vscode中的配置TypeScript环境
本文是一篇TypeScript入门教程,介绍了在VS Code中配置TypeScript环境的步骤,包括安装Node.js、使用npm安装TypeScript、配置npm镜像源、安装VS Code的TypeScript扩展,以及创建和运行一个简单的TypeScript "Hello World"程序。
TypeScript教程(一)在vscode中的配置TypeScript环境
|
4月前
|
资源调度 JavaScript 前端开发
TypeScript实战教程(一):表单上传与后端处理
本文是TypeScript实战教程的第一部分,介绍了使用TypeScript进行表单上传和后端处理的完整流程,包括环境配置、前端表单创建、使用TypeScript和Express框架搭建服务端、处理表单数据,并提供了详细的代码示例和运行测试方法。
TypeScript实战教程(一):表单上传与后端处理
|
6月前
|
JavaScript Java API
30.【TypeScript 教程】Reflect Metadata
30.【TypeScript 教程】Reflect Metadata
131 4
|
5月前
|
JavaScript 前端开发 程序员
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
88 0
|
6月前
|
JavaScript 编译器
31.【TypeScript 教程】混入(Mixins)
31.【TypeScript 教程】混入(Mixins)
42 3