0%

关于块级函数的有趣问题

块级函数

  • 先来看一道极具迷惑性的面试题

    1
    2
    3
    4
    5
    6
    7
    8
    var a;
    if(true){
    a=5;
    function a(){}
    a=0;
    console.log(a)
    }
    console.log(a)

    你可能会以为答案是0 0
    事实上,答案是0 5

  • 来看一下stackoverflow的解释
    这段代码在浏览器中是这么工作的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var a¹;
    if (true) {
    function a²() {} // hoisted
    a² = 5;
    a¹ = a²; // at the location of the declaration, the variable leaves the block
    a² = 0;
    console.log(a²)
    }
    console.log(a¹);

    这段代码的执行过程如下:

    • 在块外面和块里面都声明了a变量
    • 进入块作用域
      • function a(){}被提升至块作用域顶部
      • 执行a=5
      • 块作用域里的a被赋值为5,function a被覆盖
      • 执行到function a(){},ES6块作用域中的函数a(现在已经被赋值为5)被提升至块外最顶部,外部变量a被映射为块内a的值5
      • 此时块内a为5,因此外部的a也为5
      • a=0,块内的a被赋值为0,外部的不再受影响
      • 块内打印a,打印0
    • 离开块作用域,此时块内对块外为不可见状态
    • 打印外部变量a,此时外部a为5,因此打印5
  • debug实验





  • 在MDN官方文档中,对这种非严格模式下的块级函数声明作了解释,官方建议不要使用这种形式的函数定义,因为代码执行过程在不同的浏览器中是不同的,如果需要条件定义函数,推荐采用以下形式
    1
    2
    3
    4
    5
    let fn=null;
    if(condition){
    fn=function(){}
    }
    fn&&fn();
  • 相关链接