为什么使用 ES6 ?
每一次标准的诞生都意味着语言的完善,功能的加强。JavaScript语言本身也有一些令人不满意的地方。
- 变量提升特性增加了程序运行时的不可预测性
- 语法过于松散,实现相同的功能,不同的人可能会写出不同的代码
ES6新增变量声明:
let :
ES6中新增了用于声明变量的关键字;
作用域:
let声明的变量只在所处于的块级有效;
if (true) {
let a = 10;
}
console.log(a) // 此时会报错 a is not defined (作用域问题)
tips:
使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。
let不存在变量提升
console.log(a); // a is not defined
let a = 20;
**解释:**像上面这样,先调用再声明的,就会报错;因为变量不会自动提升;但是var 声明的变量有变量提升,可以先调用再声明。
暂时性死区
利用let声明的变量会绑定在这个块级作用域,不会受外界的影响
var tmp = 123;
if (true) {
tmp = 'abc';
let tmp;
}
解释: 只要花括号中有let变量的声明,那么就会产生let的块儿级作用域,此时外面的变量就对内部造成不来影响,因此第一行tmp = 'abc';
访问的并不是外面声明的tem
,并且再此花括号内看,tmp = 'abc';
是没有声明直接赋值,因此报错。
经典面试题(一)
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
解释: 我们知道,循环进行的时候,循环内部的函数如果没有调用那么就不会执行。 其次,在循环结束以后关键点在于变量i是全局的,函数执行时输出的都是全局作用域下的i值。也就是循环后的i的值,显然为2. 因此两次输出的值都为2 ;图解如下:
面试题(二):
let arr = [];
for (let i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
解释: 此题的关键点在于每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的
,函数执行时输出的是自己上一级(循环产生的块级作用域)作用域下的i值.因此输出的两次值也是不同的;图解如下:
let总结:
- let关键字就是用来声明变量的
- 使用let关键字声明的变量具有块级作用域
- 在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的
- 防止循环变量变成全局变量
- 使用let关键字声明的变量没有变量提升
- 使用let关键字声明的变量具有暂时性死区特性
const常量
定义: 声明常量,常量就是值(内存地址)不能变化的量;
具有块级作用域(此时与let同时记忆)
if (true) {
const a = 10;
}
console.log(a) // a is not defined
声明常量时必须赋值(没有赋值就会报错)
const PI; // Missing initializer in const declaration
常量赋值后,值不能修改
这个不能修改主要指的是地址不能修改,比如: 数值类型的数值,那么数值就代表着一个特有的地址,不能修改。然而对数组而言,只要数组没有重新被一个新的数组替代,就不算地址被修改,也就是说数组中的元素是可以通过数组[属性]=新的值
来修改的。切记不能直接给数组重新赋值eg:数组 = 新数组;
const PI = 3.14;
PI = 100; // Assignment to constant variable.
const ary = [100, 200];
ary[0] = 'a';
ary[1] = 'b';
console.log(ary); // ['a', 'b'];
ary = ['a', 'b']; // Assignment to constant variable.
const小结:
- const声明的变量是一个常量
- 既然是常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据类型,不能更改地址值
- 声明 const时候必须要给定值
let、const、var 的区别:
- 使用
var
声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象 - 使用
let
声明的变量,其作用域为该语句所在的代码块内,不存在变量提升 - 使用
const
声明的是常量,在后面出现的代码中不能再修改该常量的值