小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
前言
在ES2015之前,JavaScript中就只有两种作用域:
- 全局作用域
- 函数作用域
在
ES2015中我们新增了一个块级作用域
什么是块?
两个花括号中包裹的模块就是块,例如:
-
if 语句
if ( a > b) { console.log('块') } -
for 语句
for ( var i = 0; i < 5; i++) { console.log('块') }
以前块是没有单独作用域的,这里其实主要是var的变量提示问题
例如:
if ( true) {
var foo = '块'
}
console.log(foo)
结果:
这样会出现什么问题?
这样就会造成复杂度高的代码会出现难以维护,或者出现因为作用域导致的代码错乱,从而导致难以排查的bug。
例如
嵌套的for循环
for ( var i = 0; i < 5; i++) {
for ( var i = 0; i < 5; i++) {
console.log(i)
}
}
我们这里的循环所声明的计数器变量都命名为i,这里我们的嵌套循环应该是5*5 = 25次的情况,但是我们执行一下
结果
结果如图所示,只进行了5次循环
这个问题也很简单,因为外层的循环使用了i,内层使用了也是i,而且是用var进行声明的,他会被内层的i所覆盖,所以就导致了这个情况
for ( var i = 0; i < 5; i++) {
for ( var i = 0; i < 5; i++) {
console.log(i)
}
console.log(`内层循环结束, i = ${i}`)
}
有了块级作用域之后,我们所声明的变量就只能在他的代码块中访问,从而在一定程度上避免了,这些问题。
const 常量
常量是块级范围的,非常类似用 let 语句定义的变量。但常量的值是无法(通过重新赋值)改变的,也不能被重新声明。
const不能去修改他的指向地址,而不是不能修改里面的属性成员(const声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容(例如,其参数)。)
例如:
// 定义常量MY_FAV并赋值7
const MY_FAV = 7;
// 报错 - Uncaught TypeError: Assignment to constant variable.
MY_FAV = 20;
// MY_FAV is 7
console.log('my favorite number is: ' + MY_FAV);
// 尝试重新声明会报错
// Uncaught SyntaxError: Identifier 'MY_FAV' has already been declared
const MY_FAV = 20;
// MY_FAV 保留给上面的常量,这个操作会失败
var MY_FAV = 20;
// 也会报错
let MY_FAV = 20;
常量要求一个初始值
// 报错
// Uncaught SyntaxError: Missing initializer in const declaration
const FOO;
总结
这里我们就总结了三个关键词,let、var、const;
最佳实践:不用var,主用const、辅用let