变量作用域

作用域(Variable space)

es6 之前只有 全局变量局部变量,没有 语句块

例如代码将在控制台输出 5,因为 x 的作用域是声明了 x 的那个函数(或全局范围),而不是 if 语句块:

1
2
3
4
if (true) {
var x = 5; // 因为 var 声明的变量没有 语句块 的作用,所以 x 的作用域在 if 的父级,即全局
}
console.log(x); // 5

如果使用 ECMAScript 6 中的 let 声明,上述行为将发生变化。

1
2
3
4
if (true) {
let y = 5; // es6 新增的 let 声明的变量遵循块级作用域,作用域在 {...} 内,所以在 if 语句外获取不到。
}
console.log(y); // ReferenceError: y is not defined


变量声明提升(Variable hoisting)

由于存在变量声明提升,一个函数中所有的 var 语句应尽可能地放在接近函数顶部的地方。这将大大提升程序代码的清晰度

1
2
3
4
5
6
7
8
9
10
11
12
13
var myvar = "my value";

(function() {
console.log(myvar); // undefined 局部 myvar 被提升到函数顶部(JavaScript 变量感觉上是被“提升”或移到了函数或语句的顶部,然而提升后的变量将返回 undefined 值),返回 undefined 值。
var myvar = "local value"; // 覆盖全局 myvar
})();

// 也可写成这样:
(function() {
var myvar;
console.log(myvar); // undefined
myvar = "local value";
})();

es6let 不会发生 变量提升

1
2
console.log(x); // ReferenceError
let x = 3;


全局变量((Global variables)

全局变量实际上是全局对象的属性。

  • 浏览器 环境中 全局对象是 window / self
  • Node 环境中,全局对象是 globals
  • Web Worker 环境中,全局对象 self

参考:阮一峰【ECMAScript 6 入门】


常量(Constants)

它必须被初始化为某个值 不可改,不可在运行脚本中重新声明!作用域同 let,同一作用域中,不能使用与变量名或函数名相同的名字来命名常量!

1
const prefix = '212';

const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const 只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。参考:阮一峰【ECMAScript 6 入门】