zoukankan      html  css  js  c++  java
  • closure

    Closure:

             JavaScript词缀作用域。javascript的函数在执行时是按照定义作用域链起作用。内嵌函数f()被包含在一个作用域链中,在这个作用域链中scope被赋值为"local scope"。无论f最终在哪里被执行,这种绑定一直存在。

    var scope = "global scope";
    
    function checkscope() {
    
        var scope = "local scope";
    
        function f() {
    
            return scope;
    
        }
    
        return f;
    
    }
    
    console.log(checkscope()())

    Define your own properties

             函数是一种特殊的object类型,因此也可以有自己属性。

            

     1  // Initialize the counter property of the function object
     2 
     3          //Function decaralation are hoisted so we really can do this assignment before the function declaration
     4 
     5          uniqueInteger.counter = 0;
     6 
     7          //This function returns an unique integer each time when it is called.
     8 
     9          //It uses a property of itself to remember the next value to be returned
    10 
    11          function uniqueInteger() {
    12 
    13              return uniqueInteger.counter++;
    14 
    15          }

             但是更安全的做法是使用闭包:

                     

             下面有个更像对象编程的:函数每一次被调用都产生了新的作用域链,并且其私有变量也是独立的。

            

     1 function counter() {
     2 
     3     var n = 0;
     4 
     5     return {count:function () {
     6 
     7         return n++;
     8 
     9     }, reset:function () {
    10 
    11         n = 0;
    12 
    13     }};
    14 
    15 }
    16 
    17 var c = counter(), d = counter();
    18 
    19 console.log("c.count(): " + c.count());     //0
    20 
    21 console.log("d.count(): " + d.count());     //0 c 和 d的count是独立的
    22 
    23 console.log("c.reset(): " + c.reset());     //reset()和count()共享状态
    24 
    25 console.log("c.count(): " + c.count());     //0 因为刚把creset()了
    26 
    27 console.log("d.count(): " + d.count());     //1 d不受影响

    注意:以上我们见识了在同一个作用域链定义的闭包,会分享外层函数的私有成员。这是一个非常重要的技术,但是有时候闭包不应该共享变量如下:内嵌函数并拷贝作用域或者保留变量的静态快照。对于内嵌函数而言,i是共享的,并且是动态的。

     1 // This function returns a function that always returns v [这个不是在for循环内定义闭包,而是提前定义,在循环内被调用,每次调用就产生作用域链]
     2 
     3 function constfunc(v) { return function() { return v; }; }          
     4 
     5 // Create an array of constant functions:
     6 
     7 var funcs = [];
     8 
     9 for(var i = 0; i < 10; i++) funcs[i] = constfunc(i);
    10 
    11 // The function at array element 5 returns the value 5.
    12 
    13 funcs[5]() // => 5

    并不同于如下

     1 // Return an array of functions that return the values 0-9
     2 
     3 function constfuncs() {
     4 
     5     var funcs = [];
     6 
     7     for(var i = 0; i < 10; i++)
     8 
     9         funcs[i] = function() { return i; }; //[在for循环内定义了10个闭包,且都只是在一次constfuncs函数的一次调用中完成,而他们都引用i,因此他们分享同一个i的状态。]
    10 
    11     return funcs;
    12 
    13 }
    14 
    15 var funcs = constfuncs();
    16 
    17 console.log(funcs[5]()) // What does this return? 返回10,且所有的都返回10

    多重闭包:上面的问题我们可以通过多重闭包来解决

     1 /* 使用匿名函数来激发出 创建多重闭包函数所需要的 作用域 */
     2 
     3 function constfuncs() {
     4 
     5     var funcs = [];
     6 
     7     for(var i = 0; i < 10; i++)              {
     8 
     9                    //! funcs[i] = function() { return i; };
    10 
    11         //使用自执行的匿名函数来激发出作用域
    12 
    13         (function(){
    14 
    15             var v=i;    // 记住在这个作用域内的值,这句必须有,值的复制
    16 
    17             funcs[i]=function(){    //这个下标既可用i也可以用v,因为这个声明语句是被执行了的
    18 
    19                 console.log(i+" "+v);    // i都等于10
    20 
    21                 return v;           //在这个内层函数里,必须使用外层无法改变其值的本地变量v,如果使用i那么以在本函数执行时的i值为准;
    22 
    23             }
    24 
    25                             //!funcs[i]=function(){return i;}        //回调函数内不可使用i,如果使用i,返回的匿名的i值随着循环的变化。实际上使用了外层可改变值的i
    26 
    27         }());
    28 
    29          }
    30 
    31     return funcs;
    32 
    33 }

    中间的那一部分也可以写成如下,这样就更容易理解了:

                      

     1  funcs[i] = (function () {
     2 
     3             var v = i;    // 记住在这个作用域内的值,这句必须有,值的复制
     4 
     5             return  function () {    //这个下标既可用i也可以用v
     6 
     7                 console.log(i + " " + v);    // i都等于10
     8 
     9                 return v;           //在这个内层函数里,必须使用本地变量v
    10 
    11             }
    12 
    13             //!funcs[i]=function(){return i;}        //回调函数内不可使用i
    14 
    15         }());
    16 
    17                   

     或者:

                   

    
    

        funcs[i] = (function (v) {    //通过匿名函数传入i值,省去显示声明v,这个v是匿名函数的本地变量,外层函数无访问权限,无法改变

                                return  function () {    //这个下标既可用i也可以用v

                                     return v;           //在这个内层函数里,必须使用v;

                                    }

                            }(i));

     

                       或者还可以写作:

                      

     1  funcs[i]  =  new function () {
     2 
     3                 var v = i;    // 记住在这个作用域内的值,这句必须有,值的复制
     4 
     5                 return   function () {    //这个下标既可用i也可以用v
     6 
     7                     console.log(i + " " + v);    // i都等于10
     8 
     9                     return v;           //在这个内层函数里,必须使用v;
    10 
    11                 }
    12 
    13                 //!funcs[i]=function(){return i;}        //回调函数内不可使用i
    14 
    15          }();

                      

    注意:内嵌函数不能直接访问外部函数的this,arguments。如果需要,必须在外部函数范围定义一个变量来保证内嵌函数能正确访问。

    1 var self = this; // Save this value in a variable for use by nested funcs.
    2 
    3 var outerArguments = arguments; // Save for use by nested functions
  • 相关阅读:
    css3基础篇二
    css3基础篇一
    react基础篇六
    react基础篇五
    react基础篇四
    react基础篇三
    react基础篇二
    react基础篇一
    矩阵
    POJ 3071 Football
  • 原文地址:https://www.cnblogs.com/lansor/p/3251915.html
Copyright © 2011-2022 走看看