1.const声明常量,只读不可写,声明的时候必须立即初始化(赋值),let声明的变量只在代码块中起作用
2.不存在变量提升,变量一定要先声明,再使用
console.log(foo); // 输出undefined
console.log(bar); // 报错ReferenceError
var foo = 2;
let bar = 2;
3.let不允许在相同作用域,重复声明一个变量
// 报错
function () {
let a = 10;
var a = 1;
}
// 报错
function () {
let a = 10;
let a = 1;
}
4.ES6增加了块级作用域,ES5只有全局作用域和函数作用域
ES5中函数内部可以访问函数外部作用域,多个函数嵌套还会形成作用域链,内部变量可能会覆盖外层变量,且在for循环中的i成为了全局变量,ES6增加了块级作用域外层代码不再受内层代码影响
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
ES6允许作用域任意嵌套,内层和外层作用域可以定义相同的变量名
5.块级作用域和函数声明
在ES5中,不推荐在块级作用域块级作用域中声明函数,在严格模式下甚至会报错
// 情况一
if (true) {
function f() {}
}
// 情况二
try {
function f() {}
} catch(e) {
}
在ES6中在块级作用域中,函数的声明,类似于let,块级作用域外部不可以引用
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();//ES5中结果是‘I am inside!’,ES6中结果是‘I am outside!’因为块级作用域声明的函数外部不可以引用
}());
很显然,这种行为差异会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6在附录B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。当然这些规则只针对ES6的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let
处理。规则如下
1.允许在块级作用域声明函数,函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
2.同时,函数声明还会提升到所在的块级作用域的头部。
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
6.const在声明一个复杂类型,比如对象时,存的是该对象的地址,这个地址不可变,因此,如果给该对象添加属性是可以的,但直接把这个常量指向另一个地址就会报错
const a = [];
a.push('Hello'); // 可执行
a.length = 0; // 可执行
a = ['Dave']; // 报错
ES5只有两种声明变量的方法:var
命令和function
命令。ES6除了添加let
和const
命令,后面还会提到,另外两种声明变量的方法:import
命令和class
命令。所以,ES6一共有6种声明变量的方法。
7.全局对象的属性
在ES5中,在全局中,未声明的全局变量,自动成为全局对象window
的属性
window.a = 1; a // 1
a = 2;
window.a // 2
而在ES6中,由let
命令、const
命令、class
命令声明的全局变量,不再属于全局对象的属性。