258 ES6相关概念,关键字let
ES6相关概念(★★)
-
什么是ES6
ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。
-
为什么使用 ES6 ?
每一次标准的诞生都意味着语言的完善,功能的加强。JavaScript语言本身也有一些令人不满意的地方。
变量提升特性增加了程序运行时的不可预测性
语法过于松散,实现相同的功能,不同的人可能会写出不同的代码
let(★★★)
ES6中新增了用于声明变量的关键字let:
- let关键字就是用来声明变量的
- 使用let关键字声明的变量具有块级作用域
- 在一个大括号中,使用let关键字声明的变量才具有块级作用域, var关键字是不具备这个特点的
- 防止循环变量变成全局变量
- 使用let关键字声明的变量没有变量提升
- 使用let关键字声明的变量具有暂时性死区特性
- 【我的补充】使用let关键字声明的变量,不能被重复声明
1、let声明的变量只在所处于的块级有效
if (true) {
let a = 10;
}
console.log(a) // a is not defined
注意:使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。
if (0) {
let a = 11;
let b = 22;
console.log(a);
} else {
console.log(b); // b is not defined
}
2、不存在变量提升
console.log(a); // a is not defined
let a = 20;
3、暂时性死区
利用let声明的变量会绑定在这个块级作用域,不会受外界的影响
var tmp = 123;
if (true) {
tmp = 'abc';
let tmp;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用let关键字声明变量</title>
</head>
<body>
<script type="text/javascript">
// let关键字就是用来声明变量的
// 使用let关键字声明的变量具有块级作用域
// 在一个大括号中 使用let关键字声明的变量才具有块级作用域, var关键字是不具备这个特点的
// 防止循环变量变成全局变量
// 使用let关键字声明的变量没有变量提升
// 使用let关键字声明的变量具有暂时性死区特性
/* --------let关键字就是用来声明变量的-------- */
let a = 10;
console.log(a);
/* --------使用let关键字声明的变量具有块级作用域-------- */
if (true) {
let b = 20;
console.log(b)
if (true) {
let c = 30;
}
console.log(c); // c is not defined
}
console.log(b) // b is not defined
/* -------在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的--------- */
if (true) {
let num = 100;
var abc = 200;
}
console.log(abc); // 200
console.log(num) // num is not defined
/* -------防止循环变量变成全局变量--------- */
// 【(1)如果用var声明,则for循环结束后,i的值是2,i在全局可用; (2)此时,i 和 for循环进行绑定,在for循环外面是访问不到的。】
for (let i = 0; i < 2; i++) {}
console.log(i);
/*-----使用let关键字声明的变量没有变量提升------*/
console.log(a); // Cannot access 'a' before initialization
let a = 100;
/* -------使用let关键字声明的变量具有暂时性死区特性------- */
// 【块级作用域里的变量跟外面的同名变量没关系】
var num1 = 10;
if (true) {
let num1 = 20;
console.log(num1); // 20
}
console.log(num1); // 10
// 下面的报错,就是暂时性死区
var num2 = 66;
if (true) {
console.log(num2); // Cannot access 'num2' before initialization
let num2 = 66;
}
console.log(num2); //
/* 【我补充的】-------使用let关键字声明的变量,不能被重复声明------- */
var aa = 10
if (true) {
let aa = 20;
console.log(aa);
let aa = 30; // Identifier 'num' has already been declared
console.log(aa);
}
console.log(aa);
</script>
</body>
</html>
我的补充
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="lodash.js"></script>
</head>
<body>
<button>11</button>
<button>22</button>
<button>33</button>
<button>44</button>
<button>55</button>
</body>
</html>
<script>
let btns = document.querySelectorAll('button');
for (var i = 0; i < btns.length; i++) {
console.log(i); // 0 1 2 3 4
btns[i].addEventListener('click', function() {
// (1)当前元素的索引; (2)不是循环结束后的i;(3)改成var,则每次点击都输出5。
console.log(i);
})
}
// console.log(i); // (1)报错;(2)改成var,则输出5。
</script>
4、经典面试题
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
经典面试题图解:此题的关键点在于变量i是全局的,函数执行时输出的都是全局作用域下的i值。
let arr = [];
for (let i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
经典面试题图解:此题的关键点在于每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的,函数执行时输出的是自己上一级(循环产生的块级作用域)作用域下的i值.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>经典面试题</title>
</head>
<body>
<script type="text/javascript">
let arr = [];
// 【(1)每轮循环,都创建一个函数,循环2轮,创建了2个函数arr[0]、arr[1],这2个函数没调用,不执行。(2)如果用var,则循环结束后,i的值为2,所以调用arr[0]()、arr[1]()的时候,i的值就是2,输出的结果都是2;(3)函数执行时,函数里没有局部变量i,所以就往上一级作用域查找i,此时for循环中,用var声明的i就是全局的。】
// 【用let声明:(1)循环结束后,产生了2个块级作用域,每个作用域都有自己的i,i处于不同的块级作用域,互不影响】
for (let i = 0; i < 2; i++) {
// 【(1)函数名是arr[i];(2)函数并没有传参,所以arr[i]的i并不是函数的参数,两者没有任何关系。(2)函数执行时,函数里没有局部变量i,所以就往上一级作用域查找i,此时for循环中,用let声明的i就是块级作用域的,每个函数就到自己的块级作用域中查找i。】
arr[i] = function() {
console.log(i);
}
}
arr[0](); // 0
arr[1](); // 1
console.log('------------------------------');
let arr1 = [];
for (var i = 0; i < 2; i++) {
arr1[i] = function(i) {
console.log(i);
}
}
arr1[0](i); // 2
arr1[1](i); // 2
</script>
</body>
</html>