块级作用域let&const
js给人的感觉往往是用起来比较简单,语法上宽松。这给开发者带来便利的同时也造成了一些违反思维习惯的别扭之处。es6一些新的特性的引入,可以认为试图纠正或补齐js最初设计的缺陷。
我们一起看一下let
和const
的引入对现有的编码方式会带来哪些影响。
变量声明提升
众所周知,变量声明提升是js中非常最重要的特性之一。也是面试中常被问到的点。但对于js新人来说可能觉得难以理解,甚至违反直觉。变量没有声明之前不应该能访问啊!
console.log(v1)// undefined
var v1 = 1
console.log(v1) // 1
上面这段代码对于新手来说,undefined
的结果是难以理解的。(心想不应该报错么?)
console.log(v1) // Uncaught ReferenceError: v1 is not defined
let v1 = 1
console.log(v1) // 1
使用let
之后从逻辑上是符合开发者的思维习惯的 未声明之前使用就是会报引用错误,在声明之后访问变量的值正常返回变量值。
let
和const
声明的变量是不会被提升的,真正实现了使用前声明,声明后再使用。
全局变量不会变成window
的属性
以前在全局作用域下声明变量时,全局变量自然而然的成为了全局对象的属性如:
var a = 1
console.log(window.a === a) // true
对于这种情况前端开发工程师早已烂熟于心了。let
和 const
的引入同样改变了这种现象:
let a = 1
console.log(window.a) // undefined
console.log(a) // 1
window.a = 2
console.log(window.a) //2
console.log(a) // 1
作用域变量和对象属性分得清清楚楚。
for循环没有陷阱
看下这个前端圈用滥的面试题:
for(var i = 0; i < 5; i++){
setTimeout(function(){
console.log(i)
}, 0)
}
console.log(i)
这题固然难不倒老鸟们。但新手们十有八九会答错。0 1 2 3 4 5
。
是的,从常理来说就应该是这样的,只不过js
中缺少块级作用域的概念,var
声明的变量自然而然从for
循环的代码块外溢。
let
和const
引入后,每次循环都会创建特定于当次循环作用域的局部变量。换句话说每次循环都有与之绑定的i
值。执行完成之后即销毁。不会外溢到外层作用域。下面的代码是符合预期的:
for(let i = 0; i<5; i++){
setTimeout(function(){
console.log(i) //0 1 2 3 4
}, 0)
}
console.log(i) // ReferenceError: i is not defined
最佳实践
为了避免代码中出现意外惊喜,日常coding中首先是使用const
,可以有效避免变量被意外修改。如果变量有被修改的需求首选使用 let
。var
的使用尽量减少使用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。