1. function Foo() {
    2. getName = function () {
    3. console.log(1);
    4. };
    5. return this;
    6. }
    7. Foo.getName = function () {
    8. console.log(2);
    9. };
    10. Foo.prototype.getName = function () {
    11. console.log(3);
    12. };
    13. var getName = function () {
    14. console.log(4);
    15. };
    16. function getName() {
    17. console.log(5);
    18. }
    19. Foo.getName();
    20. getName();
    21. Foo().getName();
    22. getName();
    23. new Foo.getName();
    24. new Foo().getName();
    25. new new Foo().getName();

    20 行的会在变量 / 函数提升,被 16 行重新赋值,所以 window.getName() 是 console.log(4);

    Foo.getName(); 对应第 8 行,输出 2

    getName(); 对应 window.getName(); ,输出 4

    Foo().getName();

    1. 首先第 2 行执行,Foo() 的词法环境是 window, getName 是 window 的 getName。所以这里又重新赋值 window.getName 为 console.log(1);
    2. Foo() 执行后返回 this,这个 this 是指向 window,对应 window.getName();,输出 1

    getName(); 对应 window.getName(); ,在第 2 行执行时已经修改,输出 1


    image.png
    成员访问比 new 无参数列表的优先级高,但 new 有参数列表是与成员访问一样的,
    即 new 是对应到出现 () 为止,把那部分作构造函数

    new Foo.getName(); 是 new 第 8 行的构造函数,输出 2

    new Foo().getName(); 是 new 第 1 行的构造函数,

    1. 返回 this 是 Foo 的实例
    2. 其实例没有 getName() 方法,所以会向其原型上找
    3. 找到第 12 行,所以输出 3

    new new Foo().getName();

    1. new Foo() 是 new 第 1 行的构造函数, 返回 this 是 Foo 的实例记作 foo
    2. new foo.getName() , 成员访问比 new 无参数列表的优先级高,foo 没有 getName 又从其原型找
    3. foo.getName() 就是第 12 行的原型,然后 new Foo.prototype.getName(),输出 3
    1. 2
    2. 4
    3. 1
    4. 1
    5. 2
    6. 3
    7. 3