第一部分 第3章 函数作用域和块作用域

函数作用域

  • 函数作用域可以将内部的变量和函数定义隐藏起来

    function foo(/*参数*/){
        //...
    }
    foo(/*参数*/);
    

    但是foo会污染所在作用域,解决这个问题可以通过IIFE(立即执行函数)来解决:

    (function foo(/*参数*/){
        //...
    })(/*参数*/);
    //或者
    
    (function foo(/*参数*/){
        //...
    }(/*参数*/));
    

    这样外部无法访问foo这个函数名。当然你可以直接不写函数名,如下面这样:

    (function(/*参数*/){
        //...
    })(/*参数*/);
    

    即匿名函数,但是匿名函数有几个缺点:

    1. 匿名函数在栈追踪里不会显示出有意义的函数名,调试困难。
    2. 匿名函数在引用自身时只能使用已过期的arguments.callee引用,例如在递归中。
      萨达
    3. 可读性变差。

    综上还是建议使用具名函数。

块作用域

JavaScript没有其他编程语言(如java)中的块级作用域(在ES6之前),只有两个withtry-catch中的catch语句块,也可以用上面说的IIFE来模仿块级作用域,ES6中新增了let和const两个关键字,使得JavaScript有了块级作用域。

  • let
    let关键字可以将变量绑定到所在的任意作用域中(通常是{...}内部),换句话说,let为其声明的变量隐式地劫持了所在的块级作用域。

    let a=2;
    console.log(a);//可以正常访问
    
    {
        let a=2;
    }
    console.log(a);//Reference Error
    

    利用上面这一点,显示地声明快作用域是很有用的一个做法,比如可以在涉及闭包时提醒引擎收集不必要的垃圾。

    用let声明的变量不会进行变量声明提升。

  • const
    用const声明的变量同样是块作用域变量,但const声明的变量是固定的常量,之后任何试图修改值的操作都会引起TypeError错误。用const声明的变量不会进行变量声明提升。

你可能感兴趣的:(第一部分 第3章 函数作用域和块作用域)