一道面试题告诉了我函数在块级作用域中的提升并没有那么简单

Posted X可乐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一道面试题告诉了我函数在块级作用域中的提升并没有那么简单相关的知识,希望对你有一定的参考价值。

之前遇到一个面试题,以一个错误的角度解决了,后续有遇到类似的题,发现之前的套路走不通了,所以去研究了一下,并整理了一篇博客,话不多说,直接上题

1. 题目1

{
	function foo() { }
	foo = 1;
}
console.log(foo);

最终的打印结果是:ƒ foo() { } 所以你猜对了吗 [手动狗头]

1.1 题目1 解题思路

{
    console.log(window.foo, foo) // undefined        ƒ foo() { }
    function foo() { }
    console.log(window.foo, foo) // ƒ foo() { }      ƒ foo() { }
    foo = 1;
    console.log(window.foo, foo) // ƒ foo() { }      1
}
console.log(foo);   // ƒ foo() { }

没错,你没看错,就是粗暴的用 console 对此我只想说,没有什么事 console 解决不了 如果有,那就多写几个 [二次手动狗头]

  • 下边我们来一步一步分析
    • 第一行,打印 undefined ƒ foo() { } 说明此时,函数声明提升到了块级作用域顶部,但没有挂载到全局
    • 第二行,function foo() { } 实际执行时,会有一个隐式操作将当前 foo 的值,同步给 window
      • 通过 第一行打印结果可以得出,此时 foo 为 ƒ foo() { }
    • 第三行,打印 ƒ foo() { } ƒ foo() { } 说明此时,函数已经被挂载到全局,且在第二行执行了上述的隐式操作
    • 第四行,foo = 1,此时修改的是 块内的 foo,与外部 window 无关
    • 第五行,打印 ƒ foo() { } 1 印证上一行言论
    • 最后一行,打印 ƒ foo() { }

2. 题目2

{
    function foo() { }
    foo = 1;
    function foo() { }
}
console.log(foo);

最终的打印结果是:1 所以你又猜对了吗 [还是手动狗头]

2.1 题目2 解题思路

{
    console.log(window.foo, foo)    // undefined        ƒ foo() { }
    function foo() { }
    console.log(window.foo, foo)    // ƒ foo() { }      ƒ foo() { }
    foo = 1;
    console.log(window.foo, foo)    // ƒ foo() { }      1
    function foo() { }
    console.log(window.foo, foo)    // 1 1
}
console.log(foo);   // 1

没错 console.log YYDS [重复手动狗头]

  • 下边我们来一步一步分析
    • 第一行,打印 undefined ƒ foo() { } 说明此时,函数声明提升到了块级作用域顶部,但没有挂载到全局
    • 第二行,function foo() { } 实际执行时,会有一个隐式操作将当前 foo 的值,同步给 window
      • 通过第一行打印结果可以得出,此时 foo 为 ƒ foo() { }
    • 第三行,打印 ƒ foo() { } ƒ foo() { } 说明此时,函数已经被挂载到全局,且在 第二行执行了上述的隐式操作
    • 第四行,foo = 1,此时修改的是,块内的 foo,与外部 window 无关
    • 第五行,打印 ƒ foo() { } 1 印证上一行言论
    • 第六行,function foo() { } 实际执行时,会有一个·隐式操作·,将当前 foo 的值,同步给 window
      • 通过第五行行打印结果可以得出,此时 foo 为 1
    • 第七行,打印 1 1
    • 最后一行,打印 1

3. 题目3

{
    function foo() { }
    foo = 1;
    function foo() { }
    foo = 2;
}
console.log(foo);

最终的打印结果是:1 所以你应该能猜对了吧 [强行手动狗头]

3.1 题目3 解题思路

{
    console.log(window.foo, foo)    // undefined        ƒ foo() { }
    function foo() { }
    console.log(window.foo, foo)    // ƒ foo() { }      ƒ foo() { }
    foo = 1;
    console.log(window.foo, foo)    // ƒ foo() { }      1
    function foo() { }
    console.log(window.foo, foo)    // 1 1
    foo = 2;
    console.log(window.foo, foo)    // 1 2
}
console.log(foo);   // 1

没错,你知道我想说啥 [来个狗头]

  • 下边我们来一步一步分析
    • 第一行,打印 undefined ƒ foo() { } 说明此时,函数声明提升到了块级作用域顶部,但没有挂载到全局
    • 第二行,function foo() { } 实际执行时,会有一个隐式操作将当前 foo 的值,同步给 window
      • 通过第一行打印结果可以得出,此时 foo 为 ƒ foo() { }
    • 第三行,打印 ƒ foo() { } ƒ foo() { } 说明此时,函数已经被挂载到全局,且在 第二行执行了上述的隐式操作
    • 第四行,foo = 1,此时修改的是,块内的 foo,与外部 window 无关
    • 第五行,打印 ƒ foo() { } 1 印证上一行言论
    • 第六行,function foo() { } 实际执行时,会有一个·隐式操作·,将当前 foo 的值,同步给 window
      • 通过第五行行打印结果可以得出,此时 foo 为 1
    • 第七行,打印 1 1
    • 第八行,foo = 2,此时修改的是,块内的 foo,与外部 window 无关
    • 第九行,打印 1 2
    • 最后一行,打印 1

总结

  1. 这里要考验我们的点其实就是 块级作用域中,函数被提升后在执行到声明哪一行时不是什么也没有做,而是在执行完声明后的哪一行代码时,会将当前自身的值同步给外部 window
  2. 这也是最重要的,遇到问题多思考,对于一些看不明白的东西,一定要用 console.log 打印一下,只有对每一个代码代表的意义了解过后才能明白具体的含义是什么
  3. 进步往往是在被打倒后重新站起来的那一刻

以上是关于一道面试题告诉了我函数在块级作用域中的提升并没有那么简单的主要内容,如果未能解决你的问题,请参考以下文章

一道面试题告诉了我函数在块级作用域中的提升并没有那么简单

一道面试题告诉了我函数在块级作用域中的提升并没有那么简单

总结let 与 const新特性

js面试题知识点全解(一作用域和闭包)

ES6 之 let和const块级作用域

关于ES6