块级作用域绑定
一 var 声明及变量提升(Hoisting)机制
在函数作用域或全局作用域中通过 var 声明的变量,无论实际上是在哪里声明的,都会被当成在当前作用域顶部声明的变量,这就是我们常说的提升(Hoisting)机制。下面以一个函数为例来说明:
function getValue(condition)
{
if (condition){
var value = "blue";
// 其他代码
return value;
}else
{
// 此处可访问变量 value,其值为undefined
return null;
}
}
如果你不熟悉 JavaScript,可能会认为只有当 condition 的值为 true 时才会创建变量 value 。事实上,无论如何变量 value 都会被创建。在编译阶段,JavaScript 引擎会将上面的 getValue 函数修改成下面这样:
function getValue (condition){
var value;
if (condition){
value = "blue";
// 其他代码
return value;
}
else{
return null;
}
}
变量 value 的声明被提升至函数顶部,而初始化操作依旧留在远处执行,这就意味着在 else 子句中也可以访问到该变量,且由于此时变量尚未初始化,所以其值为 undefined。
二 块级声明
块级声明用于声明在指定块的作用域之外无法访问的变量。块级作用域(亦被称为词法作用域)存在于:
- 函数内部
- 块中(字符{和}之间的作用域)
很多类 C语言都有块级作用域,而 ECMAScript 6 引入块级作用域就是为了让 JavaScript 更灵活更普遍。
let 声明
let 声明的用法与 var 相同。 用 let 代替 var 来声明变量,就可以把变量的作用域限制在当前代码块中。由于 let 声明不会被提升,因此开发者通常将 let 声明语句放在封闭代码块的顶部,以便整个代码块都可以访问。下面是 let 声明的示例:
function getValue(condition)
{
if (condition){
var value = "blue";
// 其他代码
return value;
}else
{
// 变量 value 在此处不存在
return null;
}
// 变量 value 在此处不存在
}
禁止重声明
假设作用域中已经存在某个标识符,此时在用 let 关键字声明它就会抛出错误,举例来说:
var count = 30;
// 抛出错误
let count = 10;
在这个示例中,变量 count 被声明了两次:一次是用 var 关键字,一次是用 let 关键字。如前所述,同一作用域中不能用 let 重复定义已经存在的标识符,所以此处的 let 声明会抛出错误。但如果当前作用域内嵌另一个作用域,便可在内嵌作用域中用 let 声明同名变量,示例代码如下:
var count = 30;
if (condition){
// 不会抛出错误
let count = 40;
// 更多代码
}
由于此处的 let 实在 if 块内声明了新变量 count ,因此不会抛出错误,内部块中的 count 会遮蔽全局作用域中的 count,后者只有在 if 块外才能访问到。
const 声明
ECMAScript 6 标准还提供了 const 关键字。使用 const 声明的是常量,其值一旦被设定后不可被更改。因此,每个通过 const 声明的常量必须进行初始化,示例如下:
const maxItems = 30; // 没有问题
const name;// 语法错误,常量未初始化
在这里声明 maxItems 时进行了初始化操作,而声明 name 时没有进行赋值,因此之行后者时会抛出语法错误。
conse 和 let
const 与 let 声明都是块级标识符,所以常量也只有在当前代码块内有效,一旦执行到块外会立即被销毁。常量同样也不会被提升至作用域顶部,示例代码如下:
if (condition){
const maxItems = 5;
// 更多代码
}
// 此处无法访问 maxItems
在这段代码中,在 if 语句中声明了常量 maxItems, 语句执行一结束,maxItems 即刻被销毁,在代码块外访问不到这个常量。
与 let 相似,在同一作用域 中用 const 声明已经存在的标识符也会导致语法错误,无论该标识符使用 var ,还是 let 声明的。举例来说:
var message = "hello!";
let age = 5;
// 这两条语句都会抛出错误
const message = "Goodbye!";
const age = 30;
后两条 const 声明语句本身没问题,但由于前面的 var 和 let 声明了两个同名变量,结果代码就无法执行了。
用 const 声明对象
记住,const 声明不允许修改绑定,但允许修改值。这就意味着用 const 声明对象后,可以修改该对象的属性值。举个例子:
const max = 5;
// 抛出语法错误
max = 6;
const person = {
name = "wz"
};
// 可以修改对象属性的值
person.name = 'mm';
//抛出语法错误
person = {
name = "mm"
}
这段代码中,绑定 person 的值是一个包含一个属性的对象,改变person.name 的值,不会抛出任何错误,因为修改的是 person 包含的值。如果直接给 person 赋值,即要改变 person 的绑定,就会抛出错误。切记 const 声明不允许修改绑定,但允许修改绑定的值。