let
和const
是JavaScript里相对较新的变量声明方式。
let
在很多方面与var
是相似的,但是可以帮助大家避免在JavaScript里常见一些问题。
const
是对let
的一个增强,它能阻止对一个变量再次赋值。因为TypeScript是JavaScript的超集,所以它本身就支持
let
和const
。
如果想要全方位了解这些声明方式以及为什么推荐使用let,const来代替 var,欢迎查看官方文档:
变量声明 · TypeScript中文网 · TypeScript——JavaScript的超集
首先我们应该思考一个问题:我们声明的变量是声明了什么,而我们又希望他来做什么?
毋庸置疑的是,我们需要他们来作为一个可操作的“对象”,这个时候就涉及到了其他几个问题:
- 在哪里起作用呢?
- 是本身的变量的值还是携带的地址起作用呢?
- “对象”是否可变?
- 产生变化的是本身的值还是地址呢?
- 我们的“对象”是否可以换一个我更喜欢的名字呢?
根据这几个问题,我们就想到了关于:作用域,捕获变量,重定义及屏蔽,引用的值是否可变等。
一、var的奇怪作用域:
对于熟悉其它语言的人来说,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
都引用相同的函数作用域内的变量。 有经验的开发者们很清楚,这些问题可能在代码审查时漏掉,引发无穷的麻烦。
-
捕获变量怪异之处,比如:
for (var i = 0; i < 10; i++) {
setTimeout(function() { console.log(i); }, 100 * i);
}
代码执行的结果可能不是我们所想象的那样:从1到9依次输出;
反而是:
10
10
10
10
10
10
10
10
10
10
因为实际上我们传给setTimeout
的每一个函数表达式实际上都引用了相同作用域里的同一个i
。
二、let的块作用域
当用let
声明一个变量,它使用的是词法作用域或块作用域。 不同于使用 var
声明的变量那样可以在包含它们的函数外访问,块作用域变量在包含它们的块或for
循环之外是不能访问的。
块级作用域有两个特点:
- 块作用域变量在包含它们的块或
for
循环之外是不能访问的 - 拥有块级作用域的变量的另一个特点是,它们不能在被声明之前读或写。 虽然这些变量始终“存在”于它们的作用域里,但在直到声明它的代码之前的区域都属于 暂时性死区。
三、const的引用值不可变
const中文意思的有静态的意思,相当于说”123木头人不许动“,即被赋值后不能再改变。换句话说,const拥有与 let
相同的作用域规则,但是不能对它们重新赋值,也就是const引用的值是不可变的。
四、let与const
现在我们有两种作用域相似的声明方式,我们自然会问到底应该使用哪个。 与大多数泛泛的问题一样,答案是:依情况而定。
使用最小特权原则,所有变量除了你计划去修改的都应该使用const
。 基本原则就是如果一个变量不需要对它写入,那么其它使用这些代码的人也不能够写入它们,并且要思考为什么会需要对这些变量重新赋值。 使用 const
也可以让我们更容易的推测数据的流动。
五、变量声明时的解构(结构数组,对象解构,属性重命名)
关于解构官网上讲得十分详细明白,我自己的理解也就是”一个萝卜一个坑,萝卜不够自动补足,坑位不够自动脑补“,说的有点太俗气了,毕竟这个方式在写代码时,可是可以带来一堆便利性的。具体的看官网比较好,官方文档yyds。变量声明 · TypeScript中文网 · TypeScript——JavaScript的超集