TypeScript 变量声明

149 阅读3分钟

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

var

1、不存在块级作用域

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

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

/*

这里的 i 是在全局作用域中的,只存在一个值。

setTimeout 这个异步函数在若干毫秒后执行,

并且它是在 for 循环结束后的。在 for 循环结束后,

i 的值为 10,所以当函数被调用的时候,它会打印出 10。

*/

for (var i = 0; i < 10; i++) {

    setTimeout(function () {

        console.log(i)

    }, 100 * i)

}

//如果期望输出的结果是: 0,1,2,3,4,5,6,7,8,9

1、创建函数作用域:

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、通过 let 关键字创建块级作用域:

for (let i = 0; i < 10; i++) {

    setTimeout(function () {

        console.log(i)

    }, 100 * i)

}

通过块级声明的变量无法被代码块外部访问,这种就称为块级作用域,也成为语法作用域

块级作用域可以在函数内部和代码块{}内部创建

2、存在变量提升 

console.log(a) // undefined
var a = 1 
// 等价于

var a
console.log(a) // undefined
a = 1
// 如果将var变为let/const,会报错 a is not defined 未定义,这里也可以看出 var 与 let 在变量提升的不同:

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

let

1、let和const不存在变量提升(不可以声明提前),原因let和const之前的区域叫做暂存性死区,var的变量存在变量提升

2、使用let和const声明的变量不再属于window,不能通过window.变量名 无法访问,var声明的变量属于window

3、使用块级作用域不能在同一级中重复声明变量(let变量不能重复声明)

新增了“块级作用域”,定义在代码块中的变量在代码块被执行结束后会被释放掉:

{

var a = 10;

// 变量b只能在代码块内访问

let b = 20;

console.log(b)//20

}

console.log(a)//10

console.log(b)// b is not defined

/* 第 3 - 4 行,a 变量在 if{} 代码块中是有效的,正常输出 10。第7行,在 if{} 代码块外就被释放掉了,所以会报错误。包括在一对花括号中的一组语句称之为”代码块“,它可以替换掉

*/

function block() {
if (true) {
let a = 10
console.log(a) // 10
}

  console.log(a) // Cannot find name 'a'.ts(2304)
}

4、重定义 

var x
var x
var x

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

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

const

1、const和let除了const声明的是常量,其他和let一样

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

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

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

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

3、注意:必须在const声明常量的时候就赋值


小结

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

  • let 和 count 实现了块级作用域。
  • 所有变量除了你计划去修改的都应该使用 const
  • 尽量使用 let 和 const 来声明变量,减少 var 的使用。