送你一道JavaScript面试笔试题

225 阅读2分钟

这道题考验js综合能力的题目,相信大家在一些笔试题中也见到过,弄懂此题每个答案背后的原理后,相信大家会对一些js的知识点有种拨开迷雾见日月的的感觉。

题目如下:

function Foo() {
    getName = function () { console.log (1); };
    return this;
}
Foo.getName = function () { console.log (2);};
Foo.prototype.getName = function () { console.log (3);};
var getName = function () { console.log (4);};
function getName() { console.log (5);}

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

答案以及解释:(个人理解,还请各位多多指点,谢谢了)

1、Foo.getName();//2

Foo.getName 是访问Foo函数上存储的静态属性,所以答案是2

2、getName();//4

直接调用 getName 函数。就是访问当前上文作用域内的叫getName的函数,所以跟1 2 3都没什么关系。此处有两个坑,一是变量声明提升,二是函数表达式。

所以答案是4

3、Foo().getName();//1

此处考察了两个知识点,一个是变量作用域问题,一个是this指向问题。Foo函数的第一句 getName = function () { console.log (1)}; 是一句函数赋值语句,注意它没有var声明,所以先向当前Foo函数作用域内寻找getName变量,没有。再向当前函数作用域上层,即外层作用域内寻找是否含有getName变量,找到了,也就是第二问中的alert(4)函数,将此变量的值赋值为 function(){console.log (1)}

所以答案是1

4、getName();//1

直接调用getName函数,相当于 window.getName() ,因为这个变量已经被Foo函数执行时修改了。

所以答案是1

5、new Foo.getName();//2

此处考察的是js的运算符优先级问题。
通过查询优先级表的详细数据得知:点(.)的优先级高于new操作,相当于是:new(Foo.getName)();所以实际上将getName函数作为了构造函数来执行。

所以答案是2。

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

首先看运算符优先级括号高于new,实际执行为(new Foo()).getName()先执行Foo函数,而Foo此时作为构造函数却有返回值,之后调用实例化对象的getName函数,因为在Foo构造函数中没有为实例化对象添加任何属性,到当前对象的原型对象(prototype)中寻找getName,找到了。

所以答案是3。

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

先初始化Foo的实例化对象,然后将其原型上的getName函数作为构造函数再次new。
所以答案是3


世界很大, 多踏出一步, 就进步一步。✊!!欢迎技术交流。