变量声明
let
和const
是JavaScript里相对较新的变量声明方式。 像我们之前提到过的, let
在很多方面与var
是相似的,但是可以帮助大家避免在JavaScript里常见一些问题。 const
是对let
的一个增强,它能阻止对一个变量再次赋值。
因为TypeScript是JavaScript的超集,所以它本身就支持let
和const
。 下面我们会详细说明这些新的声明方式以及为什么推荐使用它们来代替 var
。
如果你之前使用JavaScript时没有特别在意,那么这节内容会唤起你的回忆。 如果你已经对 var
声明的怪异之处了如指掌,那么你可以轻松地略过这节。
var
声明
一直以来我们都是通过var
关键字定义JavaScript变量。
var a = 10;
也可以在函数内部定义变量:
function f() { var message = "Hello, world!"; return message; }
也可以在其它函数内部访问相同的变量。
function f() { var a = 10; return function g() { var b = a + 1; return b; } } var g = f(); g(); // returns 11;
上面的例子里,g
可以获取到f
函数里定义的a
变量。 每当 g
被调用时,它都可以访问到f
里的a
变量。 即使当 g
在f
已经执行完后才被调用,它仍然可以访问及修改a
。
function f() { var a = 1; a = 2; var b = g(); a = 3; return b; function g() { return a; } } f(); // returns 2
作用域规则
对于熟悉其它语言的人来说,var
声明有些奇怪的作用域规则。 看下面的例子:
function f(shouldInitialize: boolean) { if (shouldInitialize) { var x = 10; } return x; } f(true); // returns '10' f(false); // returns 'undefined'
变量 x
是定义在*if
语句里面*,但是我们却可以在语句的外面访问它。 这是因为 var
声明可以在包含它的函数,模块,命名空间或全局作用域内部任何位置被访问(我们后面会详细介绍),包含它的代码块对此没有什么影响。 有些人称此为* var
作用域或函数作用域*。 函数参数也使用函数作用域。
这些作用域规则可能会引发一些错误。 其中之一就是,多次声明同一个变量并不会报错:
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; }
里层的for
循环会覆盖变量i
,因为所有i
都引用相同的函数作用域内的变量。