目录
1.let命令
简单地说就是一个变量声明标识,和var的作用是相同的,但是又和var有很大的区别.
1.1 块级作用域
{
let a = 1;
var b = 2;
}
console.log(a,b);//b可以打印,a不可以
在代码块中let声明的变量只能在该代码块有效,而var超出代码块依然有效.
1.2 for循环
var a = [];
var b = [];
for(let i = 0; i < 6; i ++)
a[i] = function (){
console.log(i)
}
for(var j = 0; j < 6; j ++)
b[j] = function (){
console.log(j)
}
a[4]();//4
a[4]();//6
let声明的变量的局部的,所以输出是对应的数字;
var声明的变量是全聚德,所以输出都是i最后的状态,及6.
1.3 变量提升
相比var,let不存在变量提升,所以要使用一个let声明的变量,必须先声明再使用.
1.4 暂时性死区
只要块级作用域内存在let命令,它所声明的变量就绑定了这个区域,不在受外部的影响。
var tmp = 123;
if(true){
tmp = 'abc';//ReferenceError
let tmp;
}
暂时性死区(temporal dead zone 简称TDZ):在代码块内使用let命令声明变量之前,该变量都是不可用的。
if(true){
//TDZ开始
tmp = 'abc';
console.log(tmp);
let tmp;//TDZ结束
console.log(tmp);
tmp = 123;
console.log(tmp);
}
function bar(x = y, y = 2){
return [x, y];
}
function bar2(x = 2, y = x){
return [x, y];
}
bar();//报错
bar2();//[2, 2]
x的默认参数是y,但是此时y还没有声明,所以是TDZ。
1.5 不允许重复声明
let不允许在相同作用域内重复声明同一个变量。
//error
function(){
let a = 10;
var a = 1;
}
//error
function(){
let a = 10;
let a = 1;
}
//error
function func(arg){
let arg;
}
//right
function func(arg){
{
let arg;
}
}
2.块级作用域
传统ES5语法问题:
场景一
变量提升导致内层的tmp变量覆盖了外层的tmp变量。
var tmp = new Date();
function f(){
console.log(tmp);
if(false){
var tmp = "hello world";
}
}
f()//undefined
场景二
变量i在循环结束后泄露成了全局变量。
var s = 'hello';
for (var i = 0; i < s.length; i++){
console.log(s[i])
}
console.log(i)
将上面2个场景中的var命令变成let命令就可以避免上述的问题。
function f(){
console.log('I am outside!');
}
(function(){
if(false){
function f(){
console.log('I am inside!');
}
}
f();
}());
ES5存在变量提升:I am inside!
ES6支持块级作用域:I am outside!
如需要在外部使用块级作用域内部的变量,则需要先在外部先声明,在内部赋值。
let f;
{
let a = 'secret';
f = function(){
return a;
}
}
f()//'secret'
3.const命令
const 用来生命常量,一旦声明,其值就不可改变。
const PI = 3.1414;
PI //3.1415
PI = 3;//error
const声明时就需要立即初始化,不能留到以后赋值。
const foo;//error
const作用域和let命令相同:只在声明所在的块级作用域有效;不存在变量提升,存在暂时性死区;不可重复声明变量。
if(true){
const MAX = 5;
}
MAX//error
if(true){
console.log(MAX);//error
const MAX = 5;
}
var message = 'hello!';
let age = 25;
const message = 'Goodbye!';//error
const age = 30;//error
复合型变量,变量名不指向数据,而是指向数据所在的地址,const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变。
const foo = {};
foo.prop = 123;
foo.prop //123
foo = {} //error
const a = [];
a.push('hello');//right
a.length = 0;//right
a = ['Dave'];//error