# 写出输出结果并给出分析
# Example_0
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()
代码执行时,首先进入全局执行上下文,在执行上下文编译阶段:
- 参数处理(无);
 - 函数声明:
function Foo() { // ... }和function getName() { console.log(5) }; - 变量声明:存在一个 
var声明,由于与上面已经声明的函数同名,所以会被忽略。 
然后进入执行文的执行阶段:
赋值:
Foo.getName = function() { console.log(2) };Foo.prototype.getName = function() { console.log(3) };getName = function() { console.log(4) },覆盖之前函数声明的值;
执行:
Foo.getName();,调用赋值步骤 1 得到的方法,输出 2;getName();,调用赋值步骤 3 得到的函数,输出 4;Foo().getName();;- 直接调用 
Foo函数,其内this在非严格模式下指向window。 - 内部作用域中不存在 
getName变量,通过原型链找到外层,也就是全局的getName函数,然后赋值进行覆盖。 - 返回 
this,也就是对象window。此时Foo().getName();相当于window.getName();。 - 执行全局的 
getName方法,也就是 3-2 中改过后的方法,输出 1。 
- 直接调用 
 getName();,再次调用全局的getName方法,输出 1。new Foo.getName();:- 根据执行顺序属性的读取高于无参的 
new关键字,所以这里会先取得Foo上的getName方法。 - 通过 
new关键字调用得到的方法,输出 2。 
- 根据执行顺序属性的读取高于无参的 
 new Foo().getName();- 根据执行顺序 
new(带参数列表) 的优先级高于函数调用,所以这里先执行new Foo(),此时new Foo().getName();相当于Foo实例.getName();。 - 实例上由于不存在 
getName方法,根据原型链将找到Foo.prototype.getName方法并执行,见赋值步骤 2,输出 3。 
- 根据执行顺序 
 new new Foo().getName();:- 同上,先执行 
new Foo()得到结果new Foo实例.getName();;根据原型链找到赋值步骤 2 中的方法。 - 通过关键字 
new调用Foo原型上的getName方法,输出 3。 
- 同上,先执行