看懂这题,this、执行上下文、原型链、构造函数、变量提升都懂了!

173 阅读2分钟

话不多说,看图

image.png

直接上答案

image.png

讲解不重要就交个朋友

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’
    

如果对你有收获,请不吝点赞,欢迎指正。