先看一些前置知识:
此时输出 undefined。
- 全局作用域:全局都可以访问。
- 函数作用域:只有函数内部可以访问。
- 块级作用域:let 和 const 只能在块级作用域(一对大括号包裹的代码片段)中访问。let 和 const 在变量声明前不可以访问(因为存在暂时性死区TDZ,使变量提升没有意义,声明前访问会抛出引用错误)。
var 声明变量可以重复声明,而 let 或者 const 声明某个变量只能声明一次。var 和 let 可以先声明后赋值,默认值为 undefined。const 声明时必须赋值,且在赋值后不可以更改。
用一个例子来说明块级作用域:
<ul><li>1</li><li>2</li><li>3</li>
</ul>
<script>var oli = document.getElementsByTagName("li");for (let i = 0; i < oli.length; i++) {oli[i].onclick = function () {console.log(i)}}
</script>
此时依次点击1,2,3,之所以会输出0,1,2。是因为在 for 循环内部,每次迭代都会创建一个新的块级作用域,并且将当前迭代的值绑定到该作用域内的变量上。因此,当点击li元素时,会执行console.log(i),此时每个点击事件的处理函数都可以从自己的作用域中访问到正确的i值。
而如果将 let 改为 var,始终会输出 3。因为在循环中用var声明的变量i是一个全局变量。当点击li元素时,执行console.log(i),此时i已经是循环结束后的最后一个值3了。所以无论点击哪个li元素,输出的结果都是3。
总结:
- var 定义的变量会全局污染,而 let 和 const 定义的变量不可以全局污染(但都是可以跨标签)。
- 作用域:var(全局和函数);let 和 const(全局,函数和块级)。
- let 和 const 存在暂时性死区。
- var 可以重复声明,且不可以与 let 混用。