最近考虑跳槽,所以就去参加面试,其中面到一家金融科技公司,考题让我异常深刻,因为全程被虐。但是,可能因为我对原生js的了解多多少少还是知道些的,至少能知道面试题考察的是哪些知识点,也多亏面试官是一个特别自信同时又谦虚的人,他耐心解答我的疑问并且引导我去思考,因此侥幸通过了面试。
现在我将这个题目分享出来供大家思考,非常的有趣!!
function Foo() {
print = function () {
console.log(1)
}
return this
}
Foo.print = function() {
console.log(2)
}
Foo.prototype.print = function() {
console.log(3)
}
var print = function() {
console.log(4)
}
function print() {
console.log(5)
}
Foo.print()
print()
Foo().print()
print()
new Foo.print()
new Foo().print()
请写出以上代码输出结果,并将分析结果表达出来?
首先我们分析一下调用过程
1、Foo.print()
这里是调用了Foo这个对象的print函数,考察的知识点是js里面一切都是对象,构造函数定义后,为Foo对象添加了一个print函数,所以输出为2
2、print()
这里考察了变量提升和函数提升
var print = function() {
console.log(4)
}
function print() {
console.log(5)
}
这两段代码首先会将变量声明和函数的声明提升到作用域的顶部,就是将 var print = undefined 提升到顶部,但是赋值表达式还是在书写的位置,第二个函数只是声明了并没有赋值,所以结果输出为4
3、Foo().print()
这里可以看作两步,先执行构造函数(构造函数当作普通函数执行),执行后返回一个this,这里的this指向的是window对象。我们来看看Foo函数里面的代码
function Foo() {
print = function () {
console.log(1)
}
return this
}
一开始我就注意到里面的print没有使用var来定义,后来面试官和我说只是一个考点,主要考作用域链。当执行这个函数的时候,在函数内部如果没有找到print变量,会去查找父级作用域,因此执行Foo()函数后,print函数就重新赋值了,因此这里输出1
这里其实还有一个考点就是关于this指向的问题,大家可以去了解一下。
4、print()执行到这里,print函数已经更新了,所以也是输出1
5、new Foo.print()
这一步其实也是直接调用了Foo的属性函数print,所以输出2
6、最后一个考点是原型链的知识
先new一个构造函数生成实例,然后去调用实例对象上的print函数,发现实例对象上没有该函数,就会去实例原型上去查找该函数,因此这里输出3
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。