一道JavaScript面试题:明白Function

2017.3.27更新
本日在刷题的时刻,倏忽发明之前已经有人在议论这道题了,而且还触及到了运算符优先级的问题,这是本身一最先没有想到的。(实在有人也说:顺序写多了,天然记住了什么情况下会发作什么样的事变,然则为何会发作如许的事变,能够问起来一时还真回复不了。我就属于这类状况,所以一最先并没有考虑到运算符优先级的问题)。

关于该问题的议论:

本日看到的一道面试题,觉得对明白JavaScript的Function以及原型链和闭包很有协助。本身并试着报告一下本身的明白,迎接拍砖。

问题:

function Foo() {
    getName = function() {
        alert(1);
    }
    return this;
}
Foo.getName = function() {
    alert(2);
}
Foo.prototype.getName = function() {
    alert(3);
}
var getName = function() {
    alert(4);
};
function getName() {
    alert(5);
}
//挪用部份
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

叨教上述代码的输出效果是什么?

2,4,1,1,2,3,3

剖析

  1. Foo.getName():函数挪用输出2很好明白,直接挪用的Foo.getName();

  2. getName():函数挪用输出为4,这和变量提拔有关系了,由于在函数挪用分为两个步骤,第一进入上下文阶段,第二为实行阶段。进入上下文时,会猎取arguments函数声明变量声明。只要在实行阶段才会举行变量赋值,而第四个是函数表达式,第五个为函数声明,所以他们等同于下面的情势:

    • 进入上下文阶段:function getName(){alert(5);}

    • 实行阶段(将之前的getName函数给掩盖掉了):getName=function(){alert(4);}
      所以不管怎么挪用,答案中都应当不会涌现5。

  3. Foo().getName()与第二次getName():第三个函数挪用最先有迷惑性了。末了挪用的getName函数,实际上是全局的getName。第二次挪用就成了Foo()函数中的谁人,由于其前面没有var,也就是说这个getName并非一个私有变量,而是全局变量,所以将之前的全局中的getName函数在实行Foo()时会被掩盖掉了。因而下一次再实行getName要领的效果就变成了1,而不是之前的4了。

    别的也跟new关键字有关,由于Foo()前没有运用new,所以不会建立新的对象,而且 Foo的挪用应当属于函数挪用,所以返回的this实际上是window对象,而不是Foo实 例(并没有建立)。

  4. new Foo.getName():挪用实际上是建立了一个Foo.getName的新的实例(函数本身也是Object),在建立对象的过程当中实行到了alert(2)语句,所以就输出为2;

  5. new Foo().getName():挪用是先依据Foo.prototyoe建立一个Foo的实例,挪用getName要领时,由于本身没有getName要领,会去原型链上找,末了挪用到Foo.prototype.getName,所以就是输出为3;

  6. new new Foo().getName():第七个就是第五和第六个的连系,先建立一个Foo实例,然后再建立Foo实例的getName函数(也就是Foo.prototype.getName)的实例。在建立的过程当中,实行到alert(3)语句,所以输出3。

变化

经由过程修正Foo()函数体,能够呈现出差别的挪用变化。

  • Foo函数体内的getName前加上vargetName变成了私有变量),答案会变成:2,4,4,4,2,3,3

  • Foo函数体内的getName前加上thisgetName变成了属性),答案会变成:2,4,1,1,2,1,1

    原文作者:wly2014
    原文地址: https://segmentfault.com/a/1190000008835849
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞