• 【02】块级作用域


    【02】块级作用域
     
    魔芋总结:
    为什么要有块级作用域?
    • 01,内层变量覆盖外层变量,因为变量提升。函数提升。
    • 02,用来计数的循环变量泄露为全局变量。循环结束后,它并没有消失,泄露成了全局变量。
     
    03,ES6允许块级作用域的任意嵌套。
    04,内层作用域可以和外层作用域定义同名的变量。
    05,立即执行匿名函数(IIFE)不再必要了。
    06,函数的作用域,在其定义的块级作用域之内。
     
    需要注意的是,如果在严格模式下,函数只能在顶层作用域和函数内声明,其他情况(比如if代码块、循环代码块)的声明都会报错。
     
     
     

     
    块级作用域
    为什么需要块级作用域?
    ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
     
    第一种场景,内层变量可能会覆盖外层变量。
    var tmp = new Date();
    
    function f(){
      console.log(tmp);
      if (false){
        var tmp = "hello world";
      }
    }
    
    f() // undefined
    
     
    上面代码中,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。
     
     
    第二种场景,用来计数的循环变量泄露为全局变量。
    var s = 'hello';
    
    for (var i = 0; i < s.length; i++){
      console.log(s[i]);
    }
    
    console.log(i); // 5
    
     
    上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。
     
    ES6的块级作用域
    let实际上为JavaScript新增了块级作用域。
    function f1() {
      let n = 5;
      if (true) {
        let n = 10;
      }
      console.log(n); // 5
    }
    
     
    上面的函数有两个代码块,都声明了变量n,运行后输出5。这表示外层代码块不受内层代码块的影响。如果使用var定义变量n,最后输出的值就是10。
     
    ES6允许块级作用域的任意嵌套。
    {{{{{let insane = 'Hello World'}}}}};
    
     
    上面代码使用了一个五层的块级作用域。外层作用域无法读取内层作用域的变量。
    {{{{{let insane = 'Hello World'}
      console.log(insane); // 报错
    }}}};
    
     
    内层作用域可以定义外层作用域的同名变量。
    {{{{let insane = 'Hello World';{let insane = 'Hello World';}}}}};
    
     

     
     
     
    块级作用域的出现,实际上使得获得广泛应用的立即执行匿名函数(IIFE)不再必要了。
    // IIFE写法
    (function () {var tmp = ...;...}());
    // 块级作用域写法
    {let tmp = ...;...}
    
     
     
     

    另外,ES6也规定,函数本身的作用域,在其所在的块级作用域之内。
    function f() {
    	console.log('I am outside!');
    }
    (function () {
    	if (false) { // 重复声明一次函数f
    		function f() {
    			console.log('I am inside!');
    		}
    	}
    	f();
    }());
    
     
     
    上面代码在ES5中运行,会得到“I am inside!”,但是在ES6中运行,会得到“I am outside!”。这是因为ES5存在函数提升,不管会不会进入 if代码块,函数声明都会提升到当前作用域的顶部,得到执行;而ES6支持块级作用域,不管会不会进入if代码块,其内部声明的函数皆不会影响到作用域的外部。
     
    {
      let a = 'secret';
      function f() {
        return a;
      }
    }
    f() // 报错
    
     
    上面代码中,块级作用域外部,无法调用块级作用域内部定义的函数。如果确实需要调用,就要像下面这样处理。
    let f;{let a = 'secret';
      f = function () {return a;}}f(); // "secret"
    
     

    原文作者:阮一峰
     
     

    **

  • 相关阅读:
    2019-06-09 学习日记 day30 JS
    2019-06-08 学习日记 day29 CSS
    2019-06-07 学习日记 day28 THML
    2019-06-06 Java学习日记 day27 反射
    2019-06-05 Java学习日记 day26 网络编程
    2019-06-04 Java学习日记 day25 多线程下
    Linux安装Nginx
    Linux安装MySQL
    Linux安装Redis
    Java Swing实战(五)表格组件JTable(1)
  • 原文地址:https://www.cnblogs.com/moyuling/p/8992514.html
Copyright © 2020-2023  润新知