关于块级作用域可以参阅ES2015 块级作用域一章节。
ES2015新增let命令用来声明变量,使用方式与var类似,但区别也是巨大的。
一.let命令创建块级作用域:
使用let声明的变量只在变量声明时所在的代码块内有效(函数作用域对于let声明的变量依然有效)。
if (true) { let address = "青岛市南区"; } console.log(address);
上面的代码会报错,因为变量address只在它声明时所在的代码块中有效。
if (true) { var address = "青岛市南区"; } console.log(address);
使用var声明变量,则可以正常输出。
二.不存在变量提升现象:
使用let声明的变量不存在提升现象,看一段代码实例:
console.log(webName); var webName= "Downzz.com"; console.log(webName);
第一次会输出undefined,因为在进入执行上下文时,使用var声明变量会提升,但并没有赋值。
关于变量声明提升可以参阅JavaScript 变量和函数声明前置一章节。
console.log(url); let url = "www.downzz.com";
代码会报错,let声明变量并没有提升现象,也就是说使用let声明的变量必须先声明再使用,再来看一段代码:
console.log(typeof antzone);
变量antzone并没有声明,输出值是undefined。
console.log(typeof age); let age = 4;
上面的代码会报错,因为在let声明变量之前就使用了变量。
三.temporal dead zone:
块级作用域内,如果变量使用let声明,那么此变量就会被封闭在当前作用域内,不再受外部作用域的影响。
var url = "www.downzz.com"; function func() { console.log(url); let url = 1; } func()
代码会报错,因为函数作用域内,使用let声明了变量url,那么url就会被封闭在当前作用域中,不再受外部作用域的影响。又因为在声明之前使用变量,所以报错。再来看一段代码实例:
var url = "www.downzz.com"; if (true) { console.log(url); let url; }
上面的代码也会报错,同样的道理。
temporal dead zone指的是在一个作用域内,let声明变量之前的这块区域;如果在此区域内使用变量会报错。
四.let不允许在同一作用域重复声明变量:
不能使用let命令在同一作用域重复声明变量,代码实例:
let url = "www.downzz.com"; if (true) { let url="softwhy.com"; console.log(url); }
在不同的作用域,重复声明变量是没问题的。
if (true) { let url = "www.downzz.com"; let url="softwhy.com"; console.log(url); }
在同一作用域内,使用let重复声明变量会报错。
五.函数的声明注意事项:
在ES5严格模式下,函数声明只能存在于全局作用域和函数作用,在类似if语句这样的块中声明会报错。
代码实例如下:
"use strict"; if (true) { function func() { //code } }
代码会报错,但ES2015不会,因为会解读为函数在块级作用域内声明,但这时候,if后面大括号不能够省略。
六.全局属性:
在全局作用域使用var声明的变量,也是全局属性,代码实例如下:
var antzone = "Downzz.com"; console.log(window.antzone);
但是使用let声明的变量并非如此,代码实例如下:
let url = "softwhy.com"; console.log(window.url);
七.块级作用域的应用实例:
下面通过一个简单的代码实例,演示一下块级作用域的使用。
通过for循环批量为li元素注册click事件处理函数,点击li元素会显示对应的索引值。
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="author" content="http://www.downzz.com/" /> <title>Downzz.com</title> <script> window.onload=function(){ var lis = document.getElementsByTagName("li"); var odiv = document.getElementById("antzone"); for (var index = 0; index < lis.length; index++) { lis[index].index = index; lis[index].onclick = function () { odiv.innerHTML = this.index; } } } </script> </head> <body> <div id="antzone"></div> <ul> <li>Downzz.com一</li> <li>Downzz.com二</li> <li>Downzz.com三</li> <li>Downzz.com四</li> </ul> </body> </html>
var声明变量不会产生块级作用域,for循环完毕之后,index值最终是4,所以通过在li元素上自定义一个index属性来存储当前元素的索引的方式来实现我们的要求,当然也可以采用闭包的方式。如果采用let声明,那么就方便多了,代码如下:
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="author" content="http://www.downzz.com/" /> <title>Downzz.com</title> <script> window.onload=function(){ var lis = document.getElementsByTagName("li"); var odiv = document.getElementById("antzone"); for (let index = 0; index < lis.length; index++) { lis[index].onclick = function () { odiv.innerHTML = index; } } } </script> </head> <body> <div id="antzone"></div> <ul> <li>Downzz.com一</li> <li>Downzz.com二</li> <li>Downzz.com三</li> <li>Downzz.com四</li> </ul> </body> </html>