大神求解答JavaScript函数实例的问题
天蓬老师
天蓬老师 2017-04-10 16:24:35
0
7
520

为什么第一个图里的函数实例f1===f2就是假的。。第二个图里的函数实例f3===f4就是真的呢?还有什么是JS的函数实例呢?请大神指导一下小白

天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

reply all (7)
伊谢尔伦

每次执行aFunc的时候,会创建一个aFunc的新的执行环境。然后执行环境的作用域链就是aFunc的[[scope]]。
与此同时,aFunc的活动对象也会push到执行环境的顶端。
aFunc的活动对象包括var声明的局部变量、function声明的函数、以及aFunc的形参。
这个MyFunc就是aFunc的活动对象,会在aFunc执行的时候创建。
所以每次执行aFunc都会创建一个新的MyFunc。
因此f1 与f2 是两个不同内存地址的函数,只是函数体(函数代码)相同而已。
所以f1 == f2为false。

----------------------- 分割线 -----------------------

第二个图中,aFunc3的右侧是一个立即执行函数,aFunc3的值即是立即执行函数的返回值。
在那个立即执行函数体内,注意return function (){return MyFunc;}这个匿名函数。
这个匿名函数在创建的时候,会将作用域链保存在内部属性[[scope]]中,这个[[scope]]如图:

然后匿名函数返回给了aFunc_3。
每次执行aFunc_3(即刚才那个匿名函数),会创建一个执行环境,它内部属性[[scope]]会初始化给执行环境的作用域链,函数的活动对象再push到作用域链顶端,因为此函数内没有var声明的局部变量、function声明的函数以及参数,就为空。
然后执行return MyFunc;,此时引擎会沿着作用域链往下找,找到MyFunc就返回。
注意:这是一个顺着作用域链找标示符MyFunc的过程,并没有产生新的函数。
所以所有aFunc_3执行后返回的函数都是当时那个MyFunc。
因此f3 == f4为true。

    迷茫

    1)每次aFunc()执行后返回一个函数对象都是不同的,所以f1和f2不相同
    2)第二个片段aFunc_3指向一个立即执行函数执行后返回的函数,这个函数处在一个闭包环境中,每次执行总是返回闭包中的MyFunc函数,所以f3和f4是相同的
    3)JS中定义的任何一个函数-无论通过声明语法声明的还是通过函数表达式声明的-都是函数对象的实例,函数也是有原型的-Function

      Peter_Zhu

      你仔细观察一下,第一个例子返回的是函数声明。也就是说,声明了2个同名函数,他们在堆内存中是不一样的。

      第二个例子

      因为aFunc_3有个函数自执行的括号,因此最后的结果是

      var myFunc = function() {} aFunc_3 = function() { return myFunc; }

      于是f3 === f4就很好理解了。他们指向了同一个函数。

        巴扎黑

        看了一楼的答案之后百度了下,涨姿势了。。。
        现在我的理解,大概是这样的:

        图1和图2的区别,主要就是关于JS的函数闭包和内存回收的问题。
        图1类似于:

        var f1 = function(){ var f2 = function(){ }; return f2; };

        或者考虑的更极端一点,这样:

        f1 = function(){ f2 = function(){ }; return f2; };

        无论如何,每次执行f1函数,f2必然都会被重新赋值为一个新的函数,于是函数的返回值不相等。

        图2是这样的:

        var f1 = function(){ var f2 = function(){ }; return function(){ return f2; } }();

        更直观的理解就是:

        var f1 = function(){ return f2; }

        注意,每次执行f1函数,只执行这一句return f2;所以f2不是每次都变成新的函数。
        另外,因为f1的返回值持有了f2的引用,所以f2一直在内存里,不会被销毁。
        于是,函数的返回值都是f2。

          左手右手慢动作

          你的第一个不相等是因为,你每执行一次函数,就返回了一个新的函数(也就是说内存上位置不同),所以肯定是不相等的,第二个相等是因为,这是一个自执行的函数,你的aFun3,也就是下面的这个函数

          return function () { return MyFunc; }

          所以你在执行aFun3返回的是同一个函数,也就是MyFun
          简单的可以将上面的两种情况等价为以下的两种情况:
          第一个:

          var f1 = function () {}, f2 = function () {}, a = f1, b = f2; console.log(a === b); // 必然是false啊

          第二个:

          var f1 = function () {}, a = f1, b = f1; console.log(a === b); // true,a和b是指向同一函数
            黄舟

            何必解释得那样图文并茂,反而让人看不懂

            “js解释器在遇到函数定义的时候,会自动把函数和他可能使用的变量一起保存起来,构建一个闭包,这些变量将不会被内存回收器所回收。”

              阿神

              要搞清楚这个问题,涉及到几个概念
              作用域
              对象的比较方式
              闭包

              第一张图
              每次调用,都会在外层函数的作用域中,重新定义内层函数并命名为MyFunc,然后return出来。所以,考虑到function也是个对象,代码简化为

              function aFunc { var MyFunc = {} return MyFunc }

              又因为对象的===实际是比的内存地址

              {} === {} // false,因为两边并不是同一个{}

              第二张图
              同理简化为下面的形式

              var a = (function { var my = function (){} return function () { return my } })()

              立即执行函数表达式(Immediately Invoke Function Expression)返回一个获取闭包内变量的函数
              此时,不妨再简化一下,所有作用域往上提一层,把my放在global,整个global可以看作一个大的“闭包”,a具有访问这个global“闭包”(作用域)内变量的能力

              var my = function () {} var a = function () {return my}

              显然,无论调用多少次a,返回的都是同一个my

                Latest Downloads
                More>
                Web Effects
                Website Source Code
                Website Materials
                Front End Template
                About us Disclaimer Sitemap
                php.cn:Public welfare online PHP training,Help PHP learners grow quickly!