这篇文章为大家理一下原型链的经典面试题getName()
题目
先放上完整的题目
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().__proto__.getName();
new Foo.getName();
new new Foo().getName();
答案
这里由于某些小伙伴基础较好这里先放上答案,需要在看后面的解析啦
分析
创建GO
先提升 var声明的 getName 到最前面并且赋值为underfined ,然后提升 function Foo()赋值函数体,将 function getName() {
console.log(5); }覆盖上面声明的getName,然后从上看到下,我们发现有getName = function() { console.log(4); }赋值语句,这时我们的getName重新赋值
此时,我们的题目变成了
getName = function() {
console.log(4);
}
function Foo() {
getName = function() {
console.log(1);
}
return this;
}
Foo.getName = function() {
console.log(2);
};
Foo.prototype.getName = function() {
console.log(3);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
这里相当于调用了Foo这个构造函数里面的getName的静态方法,所以这里输出2
这里显然我们找的是全局的getName方法,从上面的分析中,我们可以看出全局的getName执行输出4,所以这里打印4
这一题分为两个步骤
- 首先我们从左到右执行Foo()执行时,由于foo内部的getName不是var声明的,也没有形参来声明他,所以这里将全局的getName = function() { console.log(1); },而且这里返回了this指向window,所以这里下面相当于window.getName()
- 由上一步,我们可以得知全局中的getName已经改变,并且Foo执行指向了全局,所以这里我们在全局中找到getName,指向1,所以这里输出1
这里基于第三问,第三问已经将全局的getName改变,所以这里输出1,不在多说
第五问 new Foo().getName();//3
这题 从左往右 先new了一个Foo(),当new的时候this指向我们new出来的新对象,而且由于Foo()本身并没有带有this.getName的方法,于是向原型链上寻找,因此找到了 Foo.prototype.getName = function() {console.log(3); },所以这里输出3
第六问 new Foo().proto.getName();//3
这一题我们可以看这个图
上面相当于Foo.prototype.getName();所以这里直接拿到3;
第七问 new Foo.getName(); //2
这里去头去尾,先看中间,拿到的是 Foo.getName = function() { console.log(2); };,所以这里打印2,我们这里可以看控制台打印
一个普通函数new出来打印结果还是原本的输出,所以这里上面打印结果为2
最后一问 new new Foo().getName();//3
从内向外,去头去尾,我们 发现这一题等价于new Foo().getName,等同于第五问,在应用上一题的方法,这里new出来结果还是为3
总结
在做原型链的题目时,可以画一个简单的原型图,再涉及到this时,牢记new指向new出来的新对象,