面向对象 Foo( ... )问题

面向对象 Foo( ... )问题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 1
        var a;

        function Foo() {
            getName = function () {
                console.log(1);
            }
            a = getName;
            return this;
        };
        
        // 闭包方法调用
        Foo().a();
        
        // 2
        Foo.getName = function () {
            console.log(2);
        };

        // 3
        Foo.prototype.getName = function () {
            console.log(3);
        };

        // 4
        var getName = function () {
            console.log(4);
        }

        // 5
        function getName() {
            console.log(5);
        }

        Foo.getName();  // 2
        getName();  //  4
        Foo().getName();  //  1
        getName();  //  1
        new Foo.getName();  // 2
        new Foo().getName();  //  3
        new new Foo().getName();  //  3

        //  代码执行前
        //  (进行变量提升,定义 var 的变量、定义并赋值 function 的变量)
        //  即先定义 '1' 处 Foo(),开辟了属于Foo的堆内存
        //  然后定义 '4' 处 getName,最后因为getName已定义所以直接 '5' 处进行赋值 = func -> 5
        
        //  代码执行阶段
        //  '2' 处定义一个Foo()的静态属性getName储蓄了一个匿名函数 = func -> 2
        //  '3' 处定义Foo的prototype,开辟了新的堆内存,并定义了一个prototype的属性getName = func -> 3
        //  '4' 处getName已提前定义,所以只要重新赋值 = func -> 4 (覆盖了func -> 5)
        
        //  执行Foo.getName(); 由 '2'处定义可知 func -> 2
        //  执行getName(); 此时执行的是全局下的getName(),即 '4' 处定义 func -> 4
        //  执行Foo().getName(); 根据运算符优先级先执行Foo()再执行getName()
        //     => 执行Foo() 
        //     => Foo函数的第一句  getName = function () { console.log(1); } 是一句函数赋值语句
        //     => 所以先在函数Foo()的作用域内查找,找不到则寻找上一级作用域,即全局作用域
        //     => 找到全局作用域内的 getName = func -> 4 重新赋值为 = func -> 1
        //     => 执行getName()
        //         => 因为Foo() return this; 而此this指向window所以Foo().getName(); 相当于 window.getName();
        //         => 所以Foo().getName(); = func -> 1
        //  执行getName(); 此时全局的getName = func -> 1
        //  执行new Foo.getName(); 根据运算符优先级先执行Foo.getName();再执行new
        //     => Foo.getName() = func -> 2   
        //     => new Foo.getName() = func -> 2
        //  执行new Foo().getName(); 根据运算符优先级先执行new Foo()再执行getName();
        //     => new Foo() 即创建了一个Foo()原型的实例,即Foo.prototype的实例
        //     => 所以原式相等于执行 Foo.prototype.getName() = func -> 3;
        //  执行new new Foo().getName(); 根据运算符优先级先执行new Foo()再执行getName();再执行new(第一个)
        //     => 即相当于 new func -> 3 = func ->3
        
    </script>
</body>
</html>

本文作者:伏月廿柒

本文链接:https://www.cnblogs.com/by0627/p/16068263.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   伏月廿柒  阅读(47)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起