Abiel1024 / blog

Abiel's blog

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

一道面试题,包含的基础知识

Abiel1024 opened this issue · comments

commented

先来看题:

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();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();

看完之后真心有点懵了,平时感觉掌握的还可以,真的这么细致的去比较,还是能发现知识的掌握程度上,真心是不够的。

首先看第一个Foo.getName(),Foo是一个构造函数,调用构造函数的 . 方法,会先从Foo本身的方法中去找,找不到则从Foo的prototype中去找对应的方法,如果找不到再从他的原型中方法中去找,再是prototype中的方法。这里显然直接就找到了。所以alert的是2

然后看第二个。这个主要考察的是变量提升。 这段代码中声明了两次getName方法,一次是函数式声明,一次是变量是声明。通常我们知道在javascript中是存在变量提升的。那具体这两次的声明是这样执行的。

function getName() { //函数变量提升
  alert(5)
}
var getName // 声明变量

getName = function () { //变量赋值
  alert(4)
};
getName();

所以很显然第二个alert的是4

然后我们再看第三个,首先执行了Foo() 在Foo()函数中,将全局的getName重新赋值了。然后再返回了this,因为当前调用对象是window 所以返回的是window对象。在.getName 就相当于是window.getName() 因为window的getName方法被重新赋值了 所以这边alert的是1

在看第四个调用getName()方法,就相当于是调用window.getName() 所以alert的是1 也就很自然了

第五个 new Foo.getName() 其实就是调用了Foo.getName()方法,所以alert的也是2

最后一个的执行顺序是先执行new Foo() 返回的一个Foo对象,再通对象去调用方法,则会在prototype方法中去找,所以alert的是3