let、const和块级作用域
let
不存在变量提升
console.log(a) // undefined
var a = 1;
console.log(b) // Uncaught ReferenceError: b is not defined
let b = 2;
var
命令会发生“变量提升”的现象,即在声明变量之前,这个变量可以使用但是值为undefined
。
而let
声明的变量,在声明语句之前使用就会报ReferenceError
。
(但也并不是说这个变量就不存在,请看下一节暂时性死区。)
暂时性死区
我们来看一个例子
var a = 1;
if(true){
console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 2;
}
如果没有let声明语句,打印结果自然是1,但是有了let声明语句,在let所在的代码块中且在let语句之前使用a,就会报ReferenceError
。
由于暂时性死区的存在,导致typeof
命令不再安全:
console.log(typeof a) // "undefined"
通常情况下,我们使用typeof
命令去判断一个未定义的变量,得到的结果是"undefined"
。
console.log(typeof a) // Uncaught ReferenceError: a is not defined
let a = 1;
由于暂时性死区的存在,会直接报错。
不允许重复声明
let
命令不能重复声明已经声明过的变量,无论这个变量是不是用let
声明的。
var a = 1;
var a = 2;
console.log(a) // "undefined"
let b = 1;
let b = 2; // Uncaught SyntaxError: Identifier 'b' has already been declared
var c = 1;
let c = 2; // Uncaught SyntaxError: Identifier 'c' has already been declared
不会绑定全局对象
let 声明的变量不会绑定要全局对象上,即便他是在全局作用域中声明的。
var a = 1;
console.log(window.a) // 1
let b = 2;
console.log(window.b) // "undefined"
const
const a // Uncaught SyntaxError: Missing initializer in const declaration
类似于let
,const
只在声明所在的块级作用域内有效,不存在变量提升,存在暂时性死区,不可重复声明,不会绑定全局对象。
块级作用域
为什么需要块级作用域?
ES5 只有全局作用域和函数作用域,没有块级作用域,这就导致会出现下面这样的问题:
- 由于变量提升,函数作用域内部的变量覆盖全局作用域的变量
var a = 1;
function fun(){
console.log(a) // "undefined"
if(false){
var a = 2;
}
}
fun()
- 循环计数作用的临时变量泄露到全局
var arr = [];
for(var i = 0; i < 5; i++){
arr[i]=i;
}
console.log(i) // 5
ES6 块级作用域
回忆一下:let
声明的变量,只在let命令所在的代码块内有效。
也就是说,let
的出现:
上面的例子用let改写:
var a = 1;
function fun(){
console.log(a) // 1
if(false){
let a = 2;
}
}
fun()
if(false)
语句生成了一个新的块级作用域,即便条件为false
不执行,外面的块级作用域可以跟她声明相同的变量:
let a = 1;
function fun(){
console.log(a) // 1
if(false){
let a = 2;
}
}
fun()
另一个例子可以通过let防止变量泄露:
var arr = [];
for(let i = 0; i < 5; i++){
arr[i]=i;
}
console.log(i) // Uncaught ReferenceError: i is not defined
块级作用域与函数声明
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();
}());
在ES5中,由于函数提升,上述例子会输出'I am inside!'。
而在ES6中,会报错:
ES6 的块级作用域必须有大括号:
if (true) let x = 1; // Uncaught SyntaxError: Lexical declaration cannot appear in a single-statement context
没有大括号不存在块级作用域,而let只能出现在当前作用域的顶层,故报错。
函数声明相同:
if (true) function f() {}
非严格模式下不会报错,严格模式下报错:”Uncaught SyntaxError: In strict mode code, functions can only be declared at top level or inside a block.“
参考
ECMAScript 6入门
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!