2

做过很多前端笔试题,有些题看起来简单,就是读程序写结果,但要么做错,要么对答案不确定,这里找到一道比较综合的题目

function Foo() {  //定义了一个名叫Foo的函数
    getName = function () { alert (1); };   //(1)函数内定义了一个函数变量
    return this;
}     
Foo.getName = function () { alert (2);};  //(2)创建了Foo的静态属性
Foo.prototype.getName = function () { alert (3);};  //(3)定义了Foo函数原型对象上的getName函数
var getName = function () { alert (4);};  //(4)通过函数变量表达式定义了一个叫getName的函数
function getName() { alert (5);}   //(5)声明了一个getName函数

//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();


第一题:

Foo.getName(); //2
Foo.getName; // function(){alert(2);}

这道题比较简单,Foo函数上的getName函数,执行的是第(2)句

第二题:

getName(); //4

我多次做这道题都会认为答案是5,其实不然。
因为变量声明提升,所以(4)拆分成两句,var getName; getName = function(){alert(3);}
其中var getName函数表达式被提升,但getName = function(){alert(3);}则不提升,(5)函数声明function getName同样提升,结果顺序就变为

function Foo() {  
    getName = function () { alert (1); };   
    return this;
}
var getName;  //变量声明提升
function getName () {alert(5);};     //变量声明提升,getName()的结果为alert(5)
Foo.getName = function () { alert (2);}; 
Foo.prototype.getName = function () { alert (3);};  
getName = function () { alert (4);};   //覆盖了getName()的结果

因此,getName()的结果为4.

第三题

Foo().getName(); //1

先执行Foo()函数,再调用其返回值对象的getName属性函数。
(1)句没有var声明,就先在Foo()里寻找getName声明,没有找到,就在外层作用域中寻找,在第(4)句找到了var getName,将此变量的值赋值为function(){alert(1);}
Foo()返回值对象this指代的是调用这个函数的对象,在这里相当于window,则Foo().getName()相当于window.getName(),而windowgetName()已经被赋值为function(){alert(1);},所以结果就为1。

Foo.getNameFoo().getName的区别

function Foo(){
    var getName = 'Zoe';
}
Foo.getName; //undefined
Foo().getName; //'Zoe'

第四题

getName(); //相当于调用window.getName(),结果为1

第五题

new Foo.getName(); //2

成员访问运算符(.)的优先级大于new,小括号()的优先级又大于(.)
所以问题改写成

new (Foo.getName)();相当于把getName当做构造函数在执行

第六题

new Foo().getName(); //3

同样因为优先级,改写成

(new Foo()).getName();

var f = Foo();
f.getName();

首先构建了一个Foo函数的实例化对象,再调用对象的getName属性,由于Foo构造函数没有添加getName属性,所以向上查找到原型对象,即(3)句,得到结果3
我犯过的一个错误,将(1)看成Foo函数的属性,其实不是的,那只是函数体内的一个变量,只能在函数体内访问,如果要表示函数属性,需要写成this.getName

第七题

new new Foo().getName(); //3

改写成

new ((new Foo()).getName)();

var f = new Foo();  
var x = f.getName;
new x(); 

bottle_
259 声望22 粉丝

好好学习,好好生活,好好工作