1.let命令
2.块级作用域
3.const命令
1.let命令
1.用let声明变量,只在块级作用域有效
在花括号{}内的变量对外部不可访问。
{
let a = 10;
}
a //a is not defined
a 访问不到花括号{}内的 a 变量。
for (let i = 0; i < 10; i++) { }
console.log(i); //i is not defined
i 访问不到for循环体内的 i 变量。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
两个 i 在不同的作用域,()是父作用域,{}是子作用域,互不影响。
2.不存在变量提升(Hoisting)
// var
console.log(foo); // 输出undefined
var foo = 2;
// 实际是
var foo;
console.log(foo); // foo存在未赋值,输出undefined
foo = 2;
// let
console.log(bar); // bar不存在,直接报错 ReferenceError
let bar = 2;
3.暂时性死区(temporal dead zone,简称 TDZ)
如果区块中存在let和const命令,这个区块就形成封闭作用域。不受外部影响。作用域内,在let声明变量前,该变量都是不可用的。
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
console.log(typeof(tmp)); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
变量一定要在声明之后使用,否则就报错。
4.不允许重复声明
// 报错
function func() {
let a = 10;
let a = 1;
}
2.块级作用域
1.ES6中的块级作用域
{{{{ // 1
let insane = 123;
{
let insane = 'Hello World';// 2
let abc = 'Hello World'
}
console.log(insane); // 123
console.log(abc); // 报错 3
}}}};
- 1允许块级作用域任意嵌套
- 2内层作用域可以定义外层作用域的同名变量
- 3外层作用域无法读取内层作用域的变量
// IIFE 写法
(function () {
var tmp = ...;
...
}());
// 块级作用域写法
{
let tmp = ...;
...
}
替代了立即执行函数表达式(IIFE)
2.块级作用域与函数声明
function f() { console.log('I am outside!'); }
(function () {
if (false) { // 1
function f() { console.log('I am inside!'); } // 2 let f = () => {}
}
f();
}());
// Uncaught TypeError: f is not a function
1允许在块级作用域之中声明函数
2块级作用域内声明的函数类似于let,对作用域之外没有影响
3但浏览器为了兼容旧代码,在实现行为上,规定函数声明类似于var,即会出现变量提升的效果(提升到全局作用域或函数作用域的头部)
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); } // 3 var
}
f();
}());
// Uncaught TypeError: f is not a function
解决方法:应该避免在块级作用域内声明函数,如果确实需要,也应该写成函数表达式,而不是函数声明语句。
// 函数声明语句
{
let a = 'secret';
function f() {
return a;
}
}
// 函数表达式
{
let a = 'secret';
let f = function () {
return a;
};
}
3.do表达式 (还在ES7...的提案中)
在块级作用域之前加上do,使它变为do表达式,然后就会返回内部最后执行的表达式的值。
let x = do {
let t = 1;
t + 10;
};
// 11
4.const命令
const a = 1;
a = 2; // error:Assignment to constant variable
▲const用来声明常量,常量的值不可改变。
const foo;
// SyntaxError: Missing initializer in const declaration
▲常量的声明必须先初始化,只声明不赋值,就会报错
const的作用域、变量不提升、暂时性死区、不可重复声明,跟let一样。