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();
分析
/*
隐式声明提升后代码如下::
var getName
function Foo() {
getName = function() {
console.log(1);
}
return this;
}
function getName() {console.log(5)}
Foo.getName = function() {console.log(2)}
Foo.prototype.getName = function() {console.log(3)} //向Foo函数的原型对象添加了个getName方法
//后面用Foo函数创建的对象的原型对象都有这个方法
getName = function() {console.log(4)}
Foo.getName(); // 调用Foo对象的getName方法 function() {console.log(2)} ==> 打印2
getName(); // 调用getName函数 有多个getName函数 根据就近原则
//找到最近的 function() {console.log(4)}==> 打印4
Foo().getName(); //成员访问从左往右执行 先执行Foo()函数 然后执行getName = function() {console.log(1);}
//因为内部没有getName变量,所以找到外部全局变量
//将外部的全局变量getName改变了 然后返回了 this==> window
//再执行window对象的getName方法 getName = function() {console.log(1);} == > 打印 1
getName(); //再次调用getName函数 function() {console.log(1);} == > 打印 1
new Foo.getName(); //按照优先级 成员访问优先级比new无参优先级高 也就是new (Foo.getName)() 先执行成员访问
//取到 function() {console.log(2)} 然后再执行 ==>打印2
//创建了对象为{function() {console.log(2)},__proto__:}
new Foo().getName(); // 按照优先级 new带参优先级跟成员访问优先级一样 所以按照从左往右计算,先执行new Foo()
//因为调用者是new 所以这里的this指向new创建的这个空对象
//然后返回空对象 向里面添加了__proto__指向Foo.prototype
//{__proto__:getName = function() {console.log(3)}}
//然后再去调用它的getName方法 自己没有找到原型对象 ==>打印3
new new Foo().getName();//按照优先级 new带参和成员访问优先级一样高,
//再按照从左往右执行 也就是 new ((new Foo()).getName )()
//首先执行new Foo() 创建了一个对象{ __proto__:{getName:function() {console.log(3)}}
//然后点语法访问成员 没有就找原型对象 {getName:function() {console.log(3)}}
//再new关键字调用这个函数打印了3
//并创建了个对象{getName:function() {console.log(3)},__proto__:}
*/