本节我们来学习块级作用域,ES5
中只有全局作用域和函数作用域。这会导致函数作用域覆盖了全局作用域,或者循环中的变量泄露为全局变量。
示例:
函数作用域覆盖全局作用域:
var a = 1;
function test() {
console.log(a); // 由于变量提升,导致内层的a变量覆盖了外层的a变量
if (true) {
var a = 10;
}
}
test(); // 输出:undefined
循环中的变量泄露为全局变量:
for(var i=0; i<5; i++) {
console.log(i); // 输出:0 1 2 3 4
}
console.log(i); // 输出:5
ES6的块级作用域
let
实际上为 JavaScript
新增了块级作用域,外层作用域无法获取到内层作用域,这样非常安全。即使外层和内层都使用相同变量名,也都互不干扰。
示例:
例如下面这段代码:
function test() {
let a = 1;
if(true){
let a = 10;
console.log(a); // 输出:10
}
console.log(a); // 输出:1
}
test(); // 调用函数
在函数 test()
和 if
语句代码块中都声明了变量 a
,但是因为 let
命令声明的变量只在块级作用域中起作用,所以在 if
中输出 a
的值为 10,在 test()
中输出 a
的值为 1,这两者互不干扰。
块级作用域与函数声明
在 ES5
中规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。而在 ES6
中引入了块级作用域,允许函数可以在块级作用域中声明。块级作用域之中,函数声明语句的行为类似于 let
,在块级作用域之外不可引用。
示例:
我们来看一个例子:
{
if(true){
function test(){
console.log("你好,侠课岛!")
}
}
}
test();
执行代码,输出结果为“你好,侠课岛!”。
但是一般考虑到兼容等问题,我们应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
示例:
上述代码使用函数表达式来写:
{
if(true){
let test = function (){
console.log("你好,侠课岛!");
};
}
}
除此之外,还有一个地方我们需要注意一下, ES6
的块级作用域必须有大括号,如果没有大括号,JavaScript
引擎就认为不存在块级作用域。
示例:
例如像下面这样写会报错:
// 声明函数
if (true)
let func = function () {};
// 声明变量
if (true) let a = 1;
报错信息如下所示:
SyntaxError: Lexical declaration cannot appear in a single-statement context
上述代码中因为没有大括号,所以不存在块级作用域,不管是声明函数还是声明变量都会报错。
网友评论