1. 全局作用域: {}外面的作用域,是全局作用域
  2. 块级作用域: 只要{ }没有和函数结合在一起,就是块级作用域
  3. 局部作用域(函数作用域): 函数后面的{}中的作用域

2-1 var 声明作用域

关键的问题在于,使用 var 操作符定义的变量会成为包含它的函数的局部变量
function test() {    
    var message = "hi"; // 局部变量 
} 
test(); 
console.log(message); // 出错

// 在函数内定义变量时省 略 var 操作符,可以创建一个全局变量

function test() {   
  message = "hi";     // 全局变量 
} 
test(); 
console.log(message); // "hi"

2-1-1 var 声明提升

使用这个关键字声明的变量会自动提升到函数作用域 顶部: 
function foo() {    
  console.log(age);   
  var age = 26; 
} 
foo();  // undefined 但不会报错

2-2 let 声明

let 跟 var 的作用差不多,但有着非常重要的区别。
明显的区别是,let 声明的范围是块作用域, 而 var 声明的范围是函数作用域。

1. 暂时性死区

let 与 var 的另一个重要的区别,就是 let 声明的变量不会在作用域中被提升。

2. 全局声明

与 var 关键字不同,使用 let 在全局作用域中声明的变量不会成为 window 对象的属性(var 声明的变量则会)

3.条件声明

var 存在变量提升    let没有
var 可以重复声明    let不可以

4. for 循环中的 let 声明

迭代变量的作用域仅限于 for 循环块内部: 
for (let i = 0; i < 5; ++i) {   
 // 循环逻辑 
} 
console.log(i); // i 没有定义

2-3 const 声明

const 的行为与 let 基本相同,
唯一一个重要的区别是 
用它声明变量时必须同时初始化变量
且尝试修改 const 声明的变量会导致运行时错误