一道常被人轻视的前端JS面试题

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();                               // 2 --解答1
getName();                                   // 4 --解答2
Foo().getName();                             // 1 --解答3
getName();                                   // 1 --解答4
new Foo.getName();                           // 2 --解答5
new Foo().getName();                         // 3 --解答6
new new Foo().getName();                     // 3 --解答7
解答1: Foo.getName()

直接访问Foo对应的静态函数

解答2: getName(),考察 声明提升
console.log(x); // 输出:function x(){}
var x=1;        // 函数表达式
function x(){}  // 函数声明

函数表达式 会拆分成 var xx=1两部分, var x为变量声明,x=1为变量赋值,声明都会提升到执行体前面, 变成:

var x;
function x(){}
console.log(x); // 所以输出为 function x(){}
x=1;
function Foo() {
    getName = function () { alert (1); };
    return this;
}
var getName;//只提升变量声明
function getName() { alert (5);}//提升函数声明,覆盖var的声明

Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};//最终的赋值再次覆盖function getName声明

getName();//最终输出4
解答3: Foo().getName(), 考察 this 和 声明提升
function Foo() {
    getName = function () { alert (1); };
    return this;
}
var getName;//只提升变量声明
function getName() { alert (5);}//提升函数声明,覆盖var的声明

Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};//最终的赋值再次覆盖function getName声明

Foo().getName();  
/*
1. Foo()返回this
2. 通过this找函数声明,在Foo内未找到,向外层找
3. 找到外层var getName声明
4. 将getName = function () { alert (4);}; 重新赋值为
        getName = function () { alert (1); };
5. 因此,最终结果为1
6. 如果向外也没找到变量声明,则在window下新建一个全局变量
*/
解答4: getName()

见解答3, 输出应该为1

解答5: new Foo.getName(),考察操作符优先级, () > . > new

等价于 new (Foo.getName)(), 输出为2

解答6: new Foo().getName()

等价于 (new Foo()).getName(), 输出为3

解答7: new new Foo().getName()

等价于 new ((new Foo()).getName)(),输出为3

补充

在传统语言中,构造函数不应该有返回值,实际执行的返回值就是此构造函数的实例化对象。而在js中构造函数可以有返回值也可以没有

  1. 没有返回值则按照其他语言一样返回实例化对象。

image_thumb1

  1. 若有返回值则检查其返回值是否为引用类型。如果是非引用类型,如基本类型(string,number,boolean,null,undefined)则与无返回值相同,实际返回其实例化对象。

image_thumb2

  1. 若返回值是引用类型,则实际返回值为这个引用类型。

image_thumb3

你可能感兴趣的:(一道常被人轻视的前端JS面试题)