ES5 只有全局作用域和函数作用域,没有块级作用域
ES6 规定暂时性死区(在代码块内,使用let、const命令声明变量之前,该变量都是不可用的)和let、const语句不出现变量提升
if (true) {
let m1 = 10;
}
console.log(m1); // 5 表示外层代码块不受内层代码块的影响
var m2 = 5;
if (true) {
var m2 = 10;
}
console.log(m2);//10 变量提升
var m3 = 5;
if (true) {
let m3 = 10;
}
console.log(m3);//5 表示外层代码块不受内层代码块的影响
let m4 = 5;
if (true) {
var m4 = 10; }
console.log(m4);//报错:Uncaught SyntaxError: Identifier 'm4' has already been declared 变量提升,相当于在全局作用域中用var重复申明了m4
ES6 允许块级作用域的任意嵌套:1.外层作用域无法读取内层作用域的变量 2.内层作用域可以定义外层作用域的同名变量
{{{{
{let name = 'dream'}
console.log(name); // 报错 Uncaught ReferenceError: insane is not defined
}}}};
{{{{
let name = 'Hello World';
{let name = 'Hello World'}
}}}};
块级作用域,使得立即执行函数表达式(IIFE)不再必要。
// IIFE 写法
(function () {
var m = ...;
...
}());
// 块级作用域写法
{
let t = ...;
...
}
ES6的浏览器规定(只在使用大括号的情况下成立,如果没有使用大括号,就会报错):1.允许在块级作用域内声明函数,函数声明类似于var(会提升到全局作用域或函数作用域的头部)
2.函数声明还会提升到所在的块级作用域的头部。所以:考虑到环境问题,避免在块级作用域内申明函数(必须则应写成函数表达式:let hhh=function(){},而不是函数申明语句:function hhh(){})
// 浏览器的 ES6 环境
function f() { console.log('get!'); }
(function () {
if (false) {//实际上在if前面提升了变量,执行了var f=undefined;在es5中是将整个函数都提升到if前面,打印出get!
// 重复声明一次函数f
function f() { console.log('get!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
与let不同的是,const申明的变量不得改变值,一旦申明必须立即赋值(初始化)
本质:变量指向的那个内存地址不可变,对于复杂类型([],{})指向的对象本身是可变的,可添加新属性。
const a = {};
a.prop = 123;// 可执行
a.push('Hello'); // 可执行
a.length = 0; // 可执行
a = ['Dave']; // 报错
a = {}; // 报错 TypeError: "foo" is read-only