JavaScript更新到ES6,增加了新的let
和const
两种命令来声明变量。我结合var
对这三个命令的作用域进行了比较。
命令名 | 作用域 |
---|---|
var | 全局 |
let | 块级 |
const | 块级 |
为了更直接的看出区别,可以看如下代码:
for (var var_i = 0; var_i < 3; var_i++) {
{
console.log(var_i);
}
}
// 全局作用域
console.log(var_i);
for (let let_i = 0; let_i < 3; let_i++) {
{
console.log(let_i);
}
}
// 块级作用域
// console.log(let_i);
{
const CONST_I = "const";
console.log(CONST_I);
}
// 块级作用域
// console.log(CONST_I);
输出结果为:
var: 0
var: 1
var: 2
var: 3
let: 0
let: 1
let: 2
const: const
可以看到源代码对于let
和const
在块外的输出,我都直接注释掉了。因为let
和const
是块级作用域,在块外输出会直接报错。
这样的特性可以解释很多问题,比如我们常见的for
循环绑定事件的问题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>let作用域和var作用域的区别</title>
</head>
<body>
<style>
.item {
width: 100px;
height: 50px;
margin: 20px;
border: 1px solid #3b3b3b;
}
</style>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</body>
</html>
用let
遍历:
let items = document.getElementsByClassName('item');
for (let index = 0; index < items.length; index++) {
items[index].onclick = function () {
items[index].style.background = 'green';
console.log(`let: ${index}`);
}
}
点击事件正常执行,并输出如下:
用var
遍历:
let items = document.getElementsByClassName('item');
for (var index = 0; index < items.length; index++) {
items[index].onclick = function () {
console.log(`let: ${index}`);
items[index].style.background = 'green';
}
}
点击事件未执行,并输出如下:
由上可知,var
由于是全局作用域,所以在循环完成后变成了3,所以在执行点击事件时,找到变量的最上级index
位于全局,已经变成了3,数组溢出,点击事件无法正常执行;而let
由于是块级作用域,在执行点击事件时,找到变量的最上级在循环体中,依然是相对应的index
,点击事件正常执行。
灵活应用变量作用域的特点,可以达到不同的开发效果。严谨的开发模式下,还是推荐多使用let
和const
这样的块级作用域,这样可以让代码更加的安全。