搜索

首页  >  问答  >  正文

javascript - if语句 对函数声明影响

console.log(e());//error

if(true){
    function e() {
        return 10;
    }
}
if(true){

    function e() {
        return 10;
    }
}
console.log(e());//10

如果函数声明提升只提升到了if作用域内,那么以上又是什么原因呢?(chrome58测试) 为何外部又能访问if的作用域内的函数? 求大神解答

滿天的星座滿天的星座2721 天前707

全部回复(3)我来回复

  • 伊谢尔伦

    伊谢尔伦2017-06-12 09:29:40

    这其实是个历史遗留问题……

    以前在ES5的时候,规范规定函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。所以,类似这样的语句其实都是非法的:

    if (true) {
        function f() {}
    }

    但是实际上各大浏览器出于兼容性的考虑,都没有遵守这个规范。

    到了现在ES6的年代,规范规定了块级作用域的存在,函数就可以在块级作用域中定义了。
    但其实事情并没有这么简单,因为这样的话,函数的定义行为就和以前不兼容了,为了保证和以前的兼容性,ES6在附录B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。


    在ES6的浏览器中,它们的行为实际上是这样的:

    1. 允许块级作用域中定义函数

    2. 函数声明实际上将会类似于使用var声明的函数表达式,函数名将会提升至当前函数作用域顶

    3. 同时函数声明也会保持在块级作用域中的提升行为

    对于你的第一个代码,如果说你仔细看看它到底报的是什么错,你会发现,错误是这样的:Uncaught TypeError: e is not a functionUncaught TypeError: e is not a function
    这个错误表示,e不是函数,换句话来说,就是e这个错误表示,e不是函数,换句话来说,就是e这个变量是存在的,但它不是函数。结合我们上面提到的三条规则,很容易就能想到,实际上它运行的是这个:

    console.log(e());//error
    
    if(true){
        var e = function() {
            return 10;
        }
    }

    经过变量提升之后,将会变成这样:

    var e;
    console.log(e());
    
    if(true){
        e = function() {
            return 10;
        }
    }

    第二段代码就不必说了吧。

    回复
    0
  • 滿天的星座

    滿天的星座2017-06-12 09:29:40

    if 语句内函数申明不会被提升,和函数表达式一样,所以第一个是语法错误,第二个会输出10

    回复
    0
  • 欧阳克

    欧阳克2017-06-12 09:29:40

    
    if(true){
        function e() {
            return 10;
        }
    }
    

    相当于 =>

    var e
    //e为undefined 所以下面报错
    console.log(e());//error
    if(true) {
        e = function() {
            return 10;
        }
        //if内的其他语句
    }
    //e已经被修改为function了,所以下面的语句正常
    console.log(e());//10

    回复
    0
  • 取消回复