一、let
1、看下代码,在函数中无论在哪里声明变量,都会自动提到函数顶部,这就是函数变量提升,它的作用于为当前函数中。
function aa() { if(bool) { var test = 'hello man' } else { console.log(test) } }
浏览器解析时
function aa() { var test // 变量提升 if(bool) { test = 'hello man' } else { //此处访问test 值为undefined console.log(test) } //此处访问test 值为undefined }
所以不用关心bool是否为true or false。实际上,无论如何test都会被创建声明。
2、当使用let 和 const 时它们的作用域为{}
function aa() { if(bool) { let test = 'hello man' } else { //test 在此处访问不到 console.log(test) } }
let的作用域是在它所在当前代码块,但不会被提升到当前函数的最顶部,所以当为false时访问不到test
3、不存在变量提升
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
上面代码中,存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。 ES6 明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
4、不允许重复声明
1) let
不允许在相同作用域内,重复声明同一个变量。
// 报错 function func() { let a = 10; var a = 1; } // 报错 function func() { let a = 10; let a = 1; }
2) 不能在函数内部重新声明参数。
function func(arg) { let arg; // 报错 } function func(arg) { { let arg; // 不报错 } }
二、const
1、常量值不能改变
const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable. 常量值不能改变
const foo; // SyntaxError: Missing initializer in const declaration 只声明不赋值报错
2、const 命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。