ES6 之前 JavaScript没有块级作用域,只有全局作用域函数作用域。ES6的到来,为我们提供了‘块级作用域’,可通过新增命令let和const来体现。

  • 作用域(Scope)
  • var和let和const的区别

作用域(Scope)

作用域是可访问变量的集合。

示例

1
2
3
4
5
function Fun() {
var value = "内层变量";
}
Fun();
console.log(value);

scope
从上面的例子中可以看出,因在全局作用域里没有声明value变量,所以在全局作用域下取值会报错。简单理解:作用域就像一个独立的区域,让变量不会外泄。

全局作用域和函数作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// --全局作用域的变量声明--
var value = "外层变量1"
var outVariable = '外层变量2'

//函数作用域
function Fun() {
var value = "内层变量1";
var inVariable = '内层变量2'
console.log('可以访问到' + outVariable)
console.log(value)
}

Fun();
console.log(value); // 不同作用域同名变量
console.log(inVariable);

scope
从上面的例子可以看出函数作用域内的value变量和全局作用域的value并不会冲突。而且外层作用域不能访问到内层的变量,而内层可以访问到外层的变量,所以
隔离变量,不同作用域下同名变量不会有冲突。
作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行。

块级作用域

ES6中新增了块级作用域,使用let声明的变量只能在块级作用域里访问,有“暂时性死区”的特性(也就是说声明前不可用)。

块作用域由 { } 包括,主要是以下几种

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 条件语句
if () {}

// switch语句
switch () {}

// for / while循环语句
for () {}
while () {}

// try...catch语句
try () catch (err) {}

// 单大括号
{}

注意: 对象的大括号内不是一个块级作用域, 因为它里面不能直接声明变量;

var和let和const的区别

  • var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。且存在变量提升现象
  • let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。不存在变量提升现象
  • const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  {
var a = 1;
let c = 2
const aa = 6
const cc //报错
console.log(c); // 2
// 可见,let能在块作用域里访问
}

console.log(a); // 1
// 可见,通过var定义的变量可以跨块作用域访问到。

console.log(c); // 报错:c is not defined
//可见,通过let定义的变量不能跨块访问

// 函数作用域
(function A() {
var b = 2;
let d = 4;
})();

console.log(b); // 报错
// 可见,通过var定义的变量不能跨函数作用域访问到

console.log(d);
//可见,通过let定义的变量不能跨函数访问