• 一道《有意思的题目》


    偶然看到老陈有意思的题目,果然有意思!在这里拿来分析分析,原题如下:

    <script type="text/javascript">
        function test(num) {
            this.m_num = 5;
            
            var func1 = function() {
                alert(num);
                alert(this.m_num);
            }
            
            this.func2 = function() {
                func1();
            }
            
            this.func3 = func1;
        }
        
        new test(1).func2();
        new test(1).func3();
    </script>

    运行结果:

    1

    undefined

    1

    5

    这道题考了至少三个知识点:

    1、函数的执行环境

    2、this 绑定

    3、匿名函数的特殊性

         首先,每个函数在执行时都会创建一个属于自己的执行环境。每个执行环境都对应一个对象,这个对象包含了在当前执行环境中定义的所有变量和函数。在 Javascript 中,是没有面向对象语言中所谓的块作用域的,变量的作用域就是通过它所在函数的执行环境限定的。换句话说,是借助于执行环境的关联对象来实现的。当一个函数在另一个函数内部执行时,它的执行环境会嵌套在包含它的函数的执行环境中。此时,内部环境可以访问外部环境中的变量,但反过来则是不允许的。当有两个及以上函数嵌套时,这些函数的执行环境组成了一个作用域链。在解析一个变量时,解析器首先会去当前执行环境中查找是否有其定义,如有则停止查找并返回值;否则会沿着作用域链向上一层执行环境中查找,如发现定义则停止查找立即返回;如还未找到,解析器会再次沿着作用域链向更外一层执行环境中查找,直至找到为止;如遍历完最外层作用域之后仍未找到,此时解析器就会把它当成一个尚未定义的变量处理。在 Web 浏览器中,任何时候,尚未定义的变量都会被当作全局作用域中的变量,全局作用域即 window 域。同时,任何自定义函数的最外层执行环境的始终是全局执行环境。

         任何函数都具有两个对象:this 和 arguments。在函数内部,可以通过 this 来访问其作用域中的变量。但 this 并不是指与函数执行环境关联的对象,而是指调用函数的对象。在浏览器中,任何函数都是作为某个对象的方法来调用的。我们可以通过函数的两个固有方法 apply() 和 call() 来指定函数的调用者,同时也改变了其执行环境。用法如下:

    function showName(){
        alert(this.name);
    }

    var jeneral1 = {name:'zhangfei'};
    var jeneral2 = {name:'zhaoyun'};

    showName.apply(jeneral1);
    showName.apply(jeneral2);

    所以,this 所指的对象并不能在函数声明时确定,而是和其具体的执行环境密切相关,是一个运行时的概念。

         在函数表达式中,我们常用匿名函数作右值:

    var init = function(){

            …

    };

         匿名函数特殊的地方在于其 this 绑定于 window 对象,但仍然遵守作用域链的规则。匿名函数常用来模仿块级作用域,如下形式:

    (function(args){

         …

    })(args)

        

    好,有了上面的了解之后再回来看题。首先,原题可以写成如下的等价形式:

    <script type="text/javascript">
        function test(num) {
            this.m_num = 5;
            
            this.func2 = function() {
                (function() {
                    alert(num);
                    alert(this.m_num);
                })();
            }
            
            this.func3 = function() {
                alert(num);
                alert(this.m_num);
            };
        }
        
        new test(1).func2();
        new test(1).func3();
    </script>

    这下就直观多了!执行函数 func2() 的时候,由于函数体包含的是一个匿名函数,它可以访问外部环境中的对象变量,故为 1 。然而它的 this 却指向 window 对象,全局作用域中没有定义 m_num ,所以是 undefined。执行 func3() 时,由于它是调用对象的方法,因此 this 指向这个对象,故为 5。

         完毕。

  • 相关阅读:
    在xp中用sc命令安装自己写的服务的具体步骤
    .net中导出excel数据不全的解决方案
    转载:20092010年中国商业智能市场分析
    xp发布多维数据集过程
    .net中导出excel时不能自动显示网格线的解决方案
    .net中访问多维数据集报错
    在xp中用DOS添加服务时,输入SC命令提示不可用的解决方案
    jenkins在奴隶机上安装dotnetsdk
    .NET Core 使用jenkins发布代码
    jenkins添加linux方法
  • 原文地址:https://www.cnblogs.com/ihada/p/2010278.html
Copyright © 2020-2023  润新知