一道常被人轻视的前端JS面试题
2018-04-12 本文已影响0人
aokaywe
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 x
和 x=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中构造函数可以有返回值也可以没有
- 没有返回值则按照其他语言一样返回实例化对象。
![](https://img.haomeiwen.com/i2368737/a36abb36ee8de934.png)
- 若有返回值则检查其返回值是否为引用类型。如果是非引用类型,如基本类型(string,number,boolean,null,undefined)则与无返回值相同,实际返回其实例化对象。
![](https://img.haomeiwen.com/i2368737/b3946ebc22568b4f.png)
- 若返回值是引用类型,则实际返回值为这个引用类型。
![](https://img.haomeiwen.com/i2368737/b963eac07ad4f0c4.png)