1.代码解析
<script>
//定义全局函数对象 (编译阶段)
function Foo(){
//重写全局 getName (运行阶段)
getName = function(){ console.log(1)}
return this;
}
//为Foo挂载私有属性 (运行阶段)
Foo.getName = function () { console.log(2)}
//为Foo挂载原型链有属性 (运行阶段)
Foo.prototype.getName = function(){ console.log(3)}
//重新定义 getName (运行阶段)
var getName = function(){ console.log(4)}
//定义全局函数 getName (编译阶段)
function getName(){
console.log(5)
}
//运行区域
Foo.getName() //2 直接执行32行代码
getName() //4 getName在运行阶段,即37行代码中被重新定义,所以输出4
Foo().getName() //1 Foo()返回window,即window.getName(),因为getName被28行代码改写,所以输出1
getName() //1 同上
new Foo.getName() //2 先把Foo.getName看作一个整体,Foo.getName刚好是一个函数,new语句会将其这个函数执行一遍(32行代码)
new Foo().getName() //3 先执行new Foo(),copy一个新的Foo副本并返回,再执行Foo副本的getName()方法,这个方法是原型链上(34行代码)
//先执行new Foo(),copy一个新的Foo副本并返回,写作Foo_2
//接着把Foo_2.getName看作一个整体,Foo_2.getName刚好是一个函数,指向34行代码
//接着再执行new Foo_2.getName(),把34行代码的函数作为模版进行一次构建,构建过程中顺带执行一遍34行代码
//34行代码输出3
new new Foo().getName()
</script>