区别有四点
-
变量作用域:
- var声明的变量具有函数作用域和全局作用域。也就是var在函数内部声明的变量只能在函数内部可见,在外部不可见
- let、const声明的变量具有块级作用域
-
变量提升:
- var有变量提升,就是变量可以在声明前使用
- let、const没有变量提升,在声明前使用就会报错(暂时性死区:变量声明之前的区域)
-
重复声明:
- var可以多次声明同一个变量,不会报错,而且后续的声明会覆盖之前的声明
- let、const在相同作用域中重复声明同一个变量就会报错
-
可变性:
- var、let声明的变量可以重新赋值和修改
- const声明的变量不可以修改,一般声明一个常量
<!-- 一个小案例 -->
<html>
<div class="btn">
<button>111</button>
<button>222</button>
<button>333</button>
</div>
</html>
<script type="text/javascript">
const btn = document.querySelectorAll('.btn button')
for (var/let i = 0; i < btn.length; i++) {
btn[i].index = i
btn[i].onclick = () => {
console.log(i)
}
}
</script>
这里使用 var 和 let 的区别
-
var是函数作用域和全局作用域,所以在for循环(块级作用域)中声明的变量,作用于整个循环体,不是单个迭代。 最终循环结果
i = btn.length,所以输出都为btn.length -
let是块级作用域,每次迭代都会创建一个新的变量绑定,所以每次迭代的变量都会保存下来,所以输出就会引用其所在迭代的特定变量值
-
暂时性死区就是这个道理,声明完变量以后就会保存在当前块级作用域
暂时性死区(TDZ)
- 变量声明之前的区域就叫暂时性死区。 就像这样:
{/*
区域A1
console.log(data) // ReferenceError
*/const data = 3
console.log(data) // 3
}
这是一个块级作用域,为了更直观一些,区域A1就是暂时性死区(进入作用域之后——声明之前)。 这里是因为JS代码有这种机制,即在进入作用域时,无论是否在代码中进行变量声明,let 和 const 声明的变量都会进入暂时性死区。
-
变量进入到暂时性死区——实际声明之间的阶段是不可访问的。 如果访问或引用变量就会报错
ReferenceError。 -
只有在变量被声明完后,才能访问。