1.块级作用域的应用
(一)if-switch-for代码中的应用
① if语句的代码就是块级作用域
// if语句的代码块是块级作用域
if (true) {
var foo = "foo"
let bar = "bar"
}
console.log(foo)
console.log(bar);
② switch语句的代码也是块级作用域
var color = 'red'
switch (color) {
case "red":
var foo = "foo"
let bar = "bar"
}
console.log(foo);
console.log(bar);
③ for语句的代码是块级作用域
// var来声明
for (var i = 0; i < 10; i++){
console.log("hello world"+i);
}
console.log(i); // 10 可以访问到
// let声明的i
for (let i = 0; i < 10; i++){
console.log("hello world"+i);
}
console.log(i); // i is not defined
(二)实际的应用
例一:获取多个按钮点击事件的监听,点击第X个按钮,就显示"第X个按钮被点击"。
① 当我们使用var来定义变量的时候,是没有块级作用域的。
const btns = document.getElementsByTagName('button')
// 想要监听这四个按钮
for (var i = 0; i < btns.length; i++){
btns[i].onclick = function () {
console.log("第" + i + "个按钮被点击");
}
}
console.log(i) // 4
无论点击哪一个按钮,最终的结果一直都是“第4个按钮被单击”,达不到要求。
解决思路:
之前在没有let类型的时候,是绑定一个立即执行函数类解决的。
const btns = document.getElementsByTagName('button')
// 想要监听这四个按钮
for (var i = 0; i < btns.length; i++){
(function (n) {
btns[n].onclick = function () {
console.log("第" + n + "个按钮被点击");
}
})(i)
// 立即执行函数,拿到i之后直接赋值给函数中的参数n
}
console.log(i);
因为for循环以后 i 就会变成 4,上面代码最后一行的输出将先执行,所以先输出 4。JS中调用函数传递参数都是值传递 ,所以当立即执行函数执行时,首先会把参数 i 的值复制一份,然后再创建函数作用域来执行函数,循环4次就会创建4个作用域。
② 使用let来定义变量,这个代码中是不能使用const的,因为这里i是会被重新赋值的。
const btns = document.getElementsByTagName('button')
for (let i = 0; i < btns.length; i++){
btns[i].onclick = function () {
console.log("第" + i + "个按钮被点击");
}
}
console.log(i);
let是有块级作用域的,因此寻找i的时候找到了上层作用域中,也就是for循环函数中的作用域。这里外边是访问不到i的,在外边访问i还会报错。
例二:对使用const定义的变量进行遍历
上文中提到的再上述的循环中可以使用let,但是不能使用const。
使用let来循环:
使用const来循环:
例三:使用ES6新增的遍历数组(对象)的方法 for…of
这种不建议使用var来定义for循环中的变量 ,因为在for循环外边还能访问到数组中最后一个元素。
如果使用let,是不会报错的,那么是否能够使用const? 可以使用,这里并没有类似于for()这种循环中的 i++的操作。