ES6中的块作用域
除了javascript之外很多编程语言都有支持块级作用域,但是在es6之前js是没有创建完整,不受约束的块作用域的能力的。对于其他编程语言的人来说对于块作用域和熟悉但是对于主要使用js的开发人员来说活血块作用域很陌生。
如下代码:
for (var i = 0; i < 6;i++) { console.log(i); }
这里定义了循环变量i,通常是因为只想在for的循环上使用这个i变量,但是有件事情可能会被你忽略的就是,这个i变量会意外的被提升到外部作用域中,或者全局或者函数中。如果变量被意外的提升在你未知的作用域中的话,将会导致未知的变量异常,或者变量被意外的混乱的复用,这将影响代码的可维护性。
在这种情况下我们需要使用到ES6中新引入的关键字let。它是var的另外一种变量声明方式。let关键字可以将变量绑定到所在块作用域中。
var s = true; if (s) { let bar = 'hello'; console.log(bar); }
如上代码 bar变量的值只存在于{} 这个块作用域中。另外也可以在声明中的任意位置都可以使用{}括号来为let创建一个用于绑定的块。
if (s) { { let sample = "sample"; console.log(sample); } }
块作用域给我们带来的另外个好处就是,整个块可以被方便地移动而不会对外部if声明的位置和语义产生影响。
还有一点重要的特性就是,使用let进行声明的变量不会在块作用域中进行提升。
{ console.log(demo); // 产生引用错误。 let demo = 2; }
有个常见的js变量提升的问题:
for (var i =0; i < 6; i++) { setTimeout(function () { console.log(i); }, 0) }
这个打印出的结果是多少呢? 如果你不知道这里的变量会被提升,你可能会以为是打印0-5的值,但是事实是它会打印出6个6。(当然这个还涉及到计时器的问题),那如何让他打印出预期的0,1,2,3,4,5的值呢?其中有一种ES6之前的解决方法就是使用IIFE表达式来解决。另一种方式就是将var 声明改为let声明形成块作用域。