话不多说,看图
直接上答案
讲解不重要就交个朋友
1、全局上下文的执行
全局上下文 script的代码执行,从上往下,依次读取代码, 这里注意一个var getName; 一个function getName; 尽管函数function getName是在var getName的后面声明的,但在函数在变量提升过程中具有优先级,so,function getName这个被提到了最顶层,且如果变量和函数名相同,函数名具有较高的优先级,变量被覆盖,然后被重新赋值了打印4的那个
function getName(){
conssole.log(5)
}
getName = function(){
consoel.log(4)
}
2、Foo.getName()执行,这步应该都能看懂打印 2,毕竟Foo自身拥有这个方法;
Foo.getName = function(){
console.log(2)
}
3、getName执行,这个根据全局上下文的执行,和变量提升,可知,此时getName被重新赋值了,打印4
getName = function(){
consoel.log(4)
}
4、Foo().getName()执行,这行代码,首先执行Foo(),然后执行.getName,主要看谁调用的getName,然后Foo()执行的时候发生了什么?
function Foo(){
getName = function(){
console.log(1);
}
return this
}
/*
* Foo()执行完,发生两件事情,
* 一 、getName再次被重写,全局变量上的 getName 再次被赋值为打印1的这个函数
* 二 、return了this,在非严格模式下,Foo作为函数独立调用this指向window,严格模式下指向undefined
*/
// 然后执行了window.getName() 打印1
5、然后getName()执行,由于上一个函数的调用,导致被重新赋值,此时仍旧是哪个打印1的函数,so 打印 1
6、开始new Foo.getName(),构造函数到底是Foo,还是Foo.getName,new 遇到第一个括号才会执行构造(个人理解),so这里打印2
7、new Foo().getName() 这里构造函数是第一个()号前的,这里Foo作为构造函数调用,那么,此时的Foo内部的this指向它的实例,然后执行实例的getName方法,那么实例没有怎么办,找原型上的getName,so 这里打印 google
new Foo() // 产生一个实例,
// 然后调用这个实例的getName方法,然而实例并没有getName,然后原型有,调用原型的getName
8、终极 new new Foo().getName()
// 分为两步 第二个new遇到第一个()进行构造,然后第二个new 遇到第一个括号构造
new Foo() 产生一个实例,把这个看成一个整体,sonFoo = new Foo()
然后 sonFoo.getName() 被作为第一个new的构造函数,进行构造,那实例的getName没有,只能去找原型的get那么方法,此时构造原型的方法中,会打印 ‘google’
如果对你有收获,请不吝点赞,欢迎指正。