ES2015: let、const 与 块级作用域

199 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文同时参与 「掘力星计划」       ,赢取创作大礼包,挑战创作激励金

前言

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)

结果:

image.png

这样会出现什么问题?

这样就会造成复杂度高的代码会出现难以维护,或者出现因为作用域导致的代码错乱,从而导致难以排查的bug。

例如

嵌套的for循环

for ( var i = 0; i < 5; i++) {
    for ( var i = 0; i < 5; i++) {
        console.log(i)
    }
}

我们这里的循环所声明的计数器变量都命名为i,这里我们的嵌套循环应该是5*5 = 25次的情况,但是我们执行一下

结果

image.png 结果如图所示,只进行了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}`)
}

image.png 有了块级作用域之后,我们所声明的变量就只能在他的代码块中访问,从而在一定程度上避免了,这些问题。

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