• 闭包总结:闭包的7种形式


      根据闭包的定义,我们知道,无论通过何种手段,只要将内部函数传递到所在的词法作用域以外,它都会持有对原始作用域的引用,无论在何处执行这个函数都会使用闭包。接下来,本文将详细介绍闭包的7种形式。

    返回值

      最常用的一种形式是函数作为返回值被返回:(返回N函数,所以外界保持对里的引用

    var F = function(){
        var b = 'local';
        var N = function(){
            return b;
        }
        return N;
    }
    console.log(F()());

    函数赋值

      一种变形的形式是将内部函数赋值给一个外部变量:(将F作用域里的函数N赋值给全局作用域的inner,所以F执行之后,inner保持了对F作用域里的引用

    var inner;
    var F = function(){
        var b = 'local';
        var N = function(){
            return b;
        };
        inner = N;
    };
    F();
    console.log(inner());

    函数参数

      闭包可以通过函数参数传递函数的形式来实现:(将F里的N作为参数给外界的Inner,F执行之后,外界Inner保持了对F里的引用

    var Inner = function(fn){
        console.log(fn());
    }
    var F = function(){
        var b = 'local';
        var N = function(){
            return b;
        }
        Inner(N);
    }
    F();

    IIFE

      由前面的示例代码可知,函数F()都是在声明后立即被调用,因此可以使用IIFE来替代。但是,要注意的是,这里的Inner()只能使用函数声明语句的形式,而不能使用函数表达式。

    function Inner(fn){
        console.log(fn());
    }
    
    (function(){
        var b = 'local';
        var N = function(){
            return b;
        }
        Inner(N);
    })();

    循环赋值

      在闭包问题上,最常见的一个错误就是循环赋值的错误。

    function foo(){
        var arr = [];
        for(var i = 0; i < 2; i++){
            arr[i] = function(){
                return i;
            }
        }
        return arr;
    }
    var bar = foo();
    console.log(bar[0]());//2 

      正确的写法如下

    function foo(){
        var arr = [];
        for(var i = 0; i < 2; i++){
            arr[i] = (function fn(j){
                return function test(){
                    return j;
                }
            })(i);
        }
        return arr;
    }
    var bar = foo();
    console.log(bar[0]());//0   

    g(s)etter

      我们通过提供getter()和setter()函数来将要操作的变量保存在函数内部,防止其暴露在外部

    var getValue,setValue;
    (function(){
        var secret = 0;
        getValue = function(){
            return secret;
        }
        setValue = function(v){
            if(typeof v === 'number'){
                secret = v;
            }
        }
    })();
    console.log(getValue());//0
    setValue(1);
    console.log(getValue());//1

    迭代器

      我们经常使用闭包来实现一个累加器

    var add = (function(){
        var counter = 0;
        return function(){
            return ++counter; 
        }
    })();
    console.log(add())//1
    console.log(add())//2  

      类似地,使用闭包可以很方便的实现一个迭代器

    function setup(x){
        var i = 0;
        return function(){
            return x[i++];
        }
    }
    var next = setup(['a','b','c']);
    console.log(next());//'a'
    console.log(next());//'b'
    console.log(next());//'c'

    总结:

      关于这七种方式自己可以好好领会下。其实说到底就是作用域外界保持了对作用域里面的引用

  • 相关阅读:
    poj 1789 Truck History(最小生成树)
    POJ 3096 Surprising Strings(STL map string set vector)
    hdu 1412 (STL list)
    POJ 1552 Doubles (C++ STL set使用)
    poj 水题系列
    洛谷P4859 已经没有什么好害怕的了
    CF1228E Another Filling the Grid
    二项式反演
    AT [ABC177F] I hate Shortest Path Problem
    [NOI2020]制作菜品
  • 原文地址:https://www.cnblogs.com/goloving/p/7775065.html
Copyright © 2020-2023  润新知