第7题: 涉及执行上下文、作用域链、IIFE的一道题

题目:下面代码输出的结果是?

{
var b = 10;
(function b(){
b = 20;
console.log(b);
})();

这里先说答案,返回的不是10,也不是20,而是b函数本身。

具名函数

这里首先声明一个b变量,然后是一个立即执行的函数表达式(IIFE),更特殊的是,该函数表达式是一个具名函数表达式(NFE)。

具名函数表达式(NFE)有两个特性:

  • 作为函数名的标识符(这里是b)只能从函数体内部访问,在函数外部访问不到(IE9+)。
  • 绑定为函数名的标识符(这里是b)不能再绑定为其他值,即该标识符绑定是不可更改的。(所以这里b = 20是无效的)

作用域链

作用域:执行上下文中包含作用域链:

在理解作用域链之前,先介绍一下作用域,作用域可以理解为执行上下文中申明的变量和作用的范围;包括块级作用域/函数作用域;

特性:声明提前:一个声明在函数体内都是可见的,函数声明优先于变量声明;
在非匿名自执行函数中,函数变量为只读状态无法修改;

[注意]:关于作用域链,IIFE、执行上下文这里不详细解释,下篇会详细介绍这些知识点。

回到本题

在本题中,由于函数声明优先于变量声明,所以在函数体内b = 20,在作用域链上先找到b函数,而b函数右是一个具名函数表达式,标识符b是不可更改的,最终打印的还是b函数体本身。

变式:打印10与20

方法一:

    var b = 10;
    (function b() {
        var b = 20;
        console.log(b);// 20
        console.log(window.b);// 10
    }());

方法二:

    var b = 10;
    (function b(){
        var b = 20; //or let b = 20;
        console.log(this.b);// 10
        console.log(b); // 20
    })();        

方法三:

    var b = 10;
    (function b(b) {
    b = 20;
    console.log(b)// 20
    })(b)

你可能感兴趣的:(前端面试题汇总)