ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
1.let命令
- 不存在变量提升
console.log(a); // undefined
var a = 0;
console.log(b) //Error
let b = 10;
2.暂时性死区
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
其实在用let关键字声明变量之前使用就是暂时性死区
咱们都知道js中的typeof方法是不会报错的,但是到啦Es6就有可能会报错啦,看下边的例子
typeof(a) // Errow 报错其实大家因该都知道啦,这里的a在声明之前就使用 啦 就是咱们上边说的暂时性死区的;
let a = 10;
- 不允许重复声明
不允许在同一作用域内声明同样的变量
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
2. 块级作用域
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
虽然这个判断执行啦,但是因为块级作用域不允许外边的块级作用域使用里边的块级作用域的东西,跟闭包的原理差不多
- 块级作用域与函数声明
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
// 情况一
if (true) {
function f() {}
}
浏览器为了兼容以前的旧代码,没有遵守这个规定,所以上边的代码是生效的,但是不建议大家使用.
function f() { console.log('我在外面!'); }
(function () {
if (false) {
function f() { console.log('我在里面'); }
}
f();
}());
上边的代码在Es5中运行会得到"我在里面"的结果,应为在判断里边的函数被提升到函数的头部,实际运行代码如下
function f() { console.log('I am outside!'); }
(function () {
function f() { console.log('I am inside!'); }
if (false) {
}
f();
}());
但是到啦Es6就不一样啦,理论上在Es6的环境下运行结果会是"我在外面",但是真的运行的时候会报错,为什么呢?
原来是应为Es6修改啦在块级作用域下声明函数的规则
允许在块级作用域内声明函数。
函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
同时,函数声明还会提升到所在的块级作用域的头部。
实际上在遵守Es6规定下的浏览器上实际的运行过程为:
function f() { console.log('我在外面!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('我在里面!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
3.const
1.const一旦声明并初始化,这个常亮的值就不得被改变
const a = 10;
a = 20;
// Error
- const一旦声明必须初始化否则报错
const a;
//Errow
3.const的作用域与let命令相同:只在声明所在的块级作用域内有效。
if (true) {
const MAX = 5;
}
console.log(MAX) // Uncaught ReferenceError: MAX is not defined
4.const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
if (true) {
console.log(MAX); // ReferenceError
const MAX = 5;
}
5.const声明的常量,也和let一样不可重复声明
var message = "Hello!";
let age = 25;
// 以下两行都会报错
const message = "Goodbye!";
const age = 30;
实际上const并不是值不可以改变,而是这个常量的内存指向的那个地址
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only