文章目录
相同点
- 嵌套定义时,采用作用域链的方式选择变量
<script type="text/javascript">
{
var name = "彭罗斯";
function getName(){
console.log(name)
}
}
getName()//彭罗斯
{
let person = "Penrose";
function getPerson(){
console.log(person)
}
}
getPerson()//Penrose
{
const P = "P";
function getP(){
console.log(P)//P
}
}
getP()
</script>
注:以下情况会影响作用域链
<script type="text/javascript">
var num = 10;
if(true){
console.log(num);
let num = 20;
}
//ReferenceError: Cannot access 'num' before initialization
</script>
//用let关键字声明变量,则此变量就会和此块级区域整体绑定
不同点
- 在同一作用域下,var可以重复声明变量,let和const不可以
<script type="text/javascript">
var p = "Hello";
var p = "Penrose";
console.log(p)
//Penrose
let p = "Hello";
let p = "Penrose";
console.log(p)
//Identifier 'p' has already been declared
const p = "Hello";
const p = "Penrose";
console.log(p)
//Identifier 'p' has already been declared
</script>
- var声明的变量是函数作用域,let和const声明的变量都是块级作用域
注:块级作用域就是用花括号{xxx}包围的区域,变量仅在此区域有效
//此时p就在个块级作用域中
<script type="text/javascript">
{
let p = "Penrose";
console.log(p)//Penrose
}
</script>
<script type="text/javascript">
if(true){
var name = "name"
let person = "person";
}
console.log(name);//name
console.log(person)//ReferenceError: person is not defined
</script>
<script type="text/javascript">
if(true){
var name = "name"
const P = "P";
}
console.log(name);//name
console.log(P)//ReferenceError: P is not defined
</script>
块级作用域的好处:防止循环变量变为全局变量
<script type="text/javascript">
for(let i = 0; i < 2; i++){
}
console.log(i)//ReferenceError: i is not defined
</script>
块级作用域应用场景
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
ul li{
list-style: none;
float: left;
width: 50px;
height: 50px;
margin-right: 10px;
border: 1px solid orange;
}
</style>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<script type="text/javascript">
let lis = document.querySelectorAll("li");
//此处使用let定义i
for(let i = 0; i < lis.length; i++){
lis[i].addEventListener("click",function(){
lis[i].style.backgroundColor = "pink"
})
}
</script>
</body>
</html>
//每一次循环完之后i的变化
{let i = 0}
{let i = 1}
{let i = 2}
//因为此时的i只在块级作用域有效,所以不会被覆盖,通过作用域链可以找到每一次循环的值
//如果使用var关键字,最后的i会被覆盖成3,循环结束后再执行回调函数,此时会发生错误
- var声明的变量可以提升(hoist),let和const声明的变量不可提升
变量提升就是将变量的声明提升到当前作用域的最前面
不存在变量提升意味着只能先声明再使用
<script type="text/javascript">
console.log(person);//undefined
var person = "Penrose"
</script>
<script type="text/javascript">
console.log(person);
let person = "Penrose"
//ReferenceError:Cannot access 'person' before initialization
</script>
- const用来声明常量,也就是内存地址不可更改,并且必须赋初始值,一般使用大写
- 对于简单数据类型,一旦赋值值不可更改
<script type="text/javascript">
const PI = 3.14;
PI = 5.2
//TypeError: Assignment to constant variable.
</script>
- 对于复杂数据类型,只能更改数据结构内部值。如更改数组某一元素的值,更改对象某一属性的值。
<script type="text/javascript">
const arr = [1,2,5,6];
arr[0] = 0;
arr.push(7)
console.log(arr)//[0, 2, 5, 6,7]
</script>
总结
var | let | const |
---|---|---|
函数作用域 | 块级作用域 | 块级作用域 |
可重复声明变量 | 不可重复声明变量 | 不可重复声明变量 |
值可更改 | 值可更改 | 值不可更改 |
变量提升 | 不存在变量提升 | 不存在变量提升 |
可选 | 可选 | 必须赋初始值 |