基本概念
let命令: 用来声明一个变量,和var非常类似。
const命令: 用来声明一个常量,常量就是不可以变化的量。
用let声明变量的注意事项
1 使用let声明的变量,所声明的变量只在命令所在的代码块内有效。
//所谓的代码块就是一对花括号,然后再花括号里面写上所需要的代码
//例如
{
let a = 1;
var b = 2;
console.log(a); //1 在代码块之内a的值可以正常被打印出来
}
console.log(a); //显示a未定义
console.log(b); //2 可以发现b是可以正常被访问到的
//说明了在代码块之外是拿不到代码块内使用let定义的变量a的
结论:这个例子说明了let只在所声明的代码块内才有效
2 使用let命令声明的变量在域解析的时候不会被提升。
例如:
在ES5中
console.log(a); //undefined
var a = 1;
我们发现这个时候是可以访问到这个a的,他的值是undefined,
因为在域解析的时候,它的变量被提升了,
这其实是一种非常不合理的行为
现在我们使用let去声明一个变量
console.log(b); //报错 告诉你这个时候b还未定义
let b = 1;
在例如
typeof c;
let c = 10;
//报错
在例如
let f = 10;
function fn(){
f = 7; //ES6术语:暂时性死区
let f = 2;
}
fn();
// 依然报错,原因是在函数内部我们使用了let声明了这个变量
3 let不允许在同一个作用域下声明已经存在的变量。
var a = 1;
let a; //依然报错 提示变量a已经被声明过了
在如:
let b = 1;
let b = 2; //依然报错 提示变量a已经被声明过了
let在for循环中的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script type="text/javascript">
var btns = document.querySelector('button');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function(){
console.log(i); //5 无论点击哪个都是i循环完成之后的值
}
}
</script>
</head>
<body>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</body>
</html>
如要解决这个问题,我们此前的解决的方法是给每个按钮增加一个自定义属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script type="text/javascript">
var btns = document.querySelector('button');
btns[i].index = i;
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function(){
console.log(this.index); //这是就可以获取到每次循环时的a了
}
}
</script>
</head>
<body>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</body>
</html>
除了上述以外,我们还可以采用闭包的方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script type="text/javascript">
var btns = document.querySelector('button');
for (var i = 0; i < btns.length; i++) {
(function(i){
btns[i].onclick = function(){
console.log(i);//可以获取到每次循环时的a了
}
})(i)
}
</script>
</head>
<body>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</body>
</html>
现在有了let咱们就不用那么麻烦了,我们直接在循环当中直接用let对变量进行初始化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script type="text/javascript">
var btns = document.querySelector('button');
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = function(){
console.log(i); //可以获取到每次循环时的a了
}
}
</script>
</head>
<body>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</body>
</html>
在for循环中如果使用let对变量进行初始化,还会有一个非常特别的地方
在循环语句之内是一个父作用域,在循环体之中是一个子作用域
for (var i = 0; i < 3; i++) {
let i = 10;
console.log(i); //10
}
console.log(i); //未定义
这个例子说明了,在循环体内的i的值是不会受到循环体的i的影响的,也就是说循环语句的父作用域和循环里的子作用域是分离的,
第二个console.log(1)打印报错,说i未定义;
这就说明了使用let初始化这个变量的时候,只在for循环语句中有用
循环之后就不是到for循环所在的作用域当中的
const命令同样有上面let的1、2、3三条特点,
第一 所声明的常量只在其所在的代码块内有效,
第二 声明的常量不会被提升,
第三 不能声明已经被声明过的常量,
除了这些,
在使用const声明常量的时候需要注意的两点:
1.声明的时候必须赋值
var a; //正确
let b; //正确
const c; //报错
2.声明的常量存储简单的数据类型时候不可以改变其值,
如果储存的是对象,那么引用不可以被改变,
至于对象里面的数据如何变化,是没有关系的
const a = 1;
a = {}; //报错
const obj = {a:10};
obj.a = 20;//这句代码事实上只是修改了对象里面的数据,但是并没有修改常量obj的引用
//所以浏览器不报错
console.log(obj);我们发现a的值已经被修改成20了