一、let

let

特性

  1. 声明的变量只在let所在的代码块内生效
    {
     	let a = 10;
    	var b = 1;
    }	
    a // ReferenceError: a is not defined.
    b // 1
    
  2. 不存在变量声明提升
    // var 的情况
    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;
    
  3. 暂时性死区(即在变量声明前不能赋值)
    if (true) {
         // TDZ开始
         tmp = 'abc'; // ReferenceError
         console.log(tmp); // ReferenceError
       
         let tmp; // TDZ结束
         console.log(tmp); // undefined
       
         tmp = 123;
         console.log(tmp); // 123
    }
    
  4. 在相同作用域内,不允许重复声明
    // 报错
    function func() {
     let a = 10;
     var a = 1;
    }
    
    // 报错
    function func() {
     let a = 10;
     let a = 1;
    }
    

块级作用域的概念

let实际上为 JavaScript 新增了块级作用域。它让一些不合理的场景变的合理

  1. 场景1 内层变量可能会覆盖外层变量
    var tmp = new Date();
    
    function f() {
      console.log(tmp);
      if (false) {
        var tmp = 'hello world';
      }
    }
    
    f(); // undefined
    

上面代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。

2.场景2 用来计数的循环变量泄露为全局变量

var s = 'hello'
	
for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}

console.log(i); // 5

上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

ES6 的块级作用域

function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5
}

上面的函数有两个代码块,都声明了变量n,运行后输出 5。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量n,最后输出的值才是 10。

特性

1. 允许块级作用域的任意嵌套

 {{{{{let insane = 'Hello World'}}}}};

2. 外层作用域无法读取内层作用域的变量,

 {{{{
  {let insane = 'Hello World'}
  console.log(insane); // 报错
}}}}

3. 内层作用域可以定义外层作用域的同名变量

{{{{
  let insane = 'Hello World';
  {let insane = 'Hello World'}
}}}}

块级作用域与函数声明

函数能不能在块级作用域之中声明?这是一个相当令人混淆的问题。

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

// 情况一
if (true) {
  function f() {}
}

// 情况二
try {
  function f() {}
} catch(e) {
  // ...

上面两种函数声明,根据 ES5 的规定都是非法的

但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数,因此上面两种情况实际都能运行,不会报错。

ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

块级作用域声明函数规则

1. 允许在块级作用域内声明函数。
2. 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
3. 同时,函数声明还会提升到所在的块级作用域的头部。

你可能感兴趣的:(ES6)