zoukankan      html  css  js  c++  java
  • 02函数-03-闭包

    1、闭包的概念

    闭包是一种特殊的程序结构,即 函数A中定义了另一个函数a,内部函数a引用了外部函数A的参数和局部变量,最终A会返回一个保存了相关参数和变量的函数a

    简洁地说,外层函数将保存了信息的可执行内层函数作为结果返回

    来看个例子:
    //求和功能  
    function lazy_sum(arr) {
        var sum = function () {
            return arr.reduce(function (x, y) {
                return x + y;
            });
        }
        return sum;
    }
    //当调用该函数时不会直接返回结果,而是返回函数 --e.g.--> // var f = lazy_sum([1, 2, 3, 4, 5]); --> 得到 function sum()
    //调用函数时,才得到真正的结果 --e.g.--> // f(); --> 得到 15
    //另,即使传入相同参数的两个函数A,返回的函数a也是不同的

    2、闭包的小坑

    闭包的返回函数,是没有立刻执行的,直到调用该函数才会执行,这意味着,如果是引用了循环变量,会变成如下情况:
    function count() {
        var arr = [];
        for (var i=1; i<=3; i++) {
            arr.push(function () {
                return i * i;
            });
        }
        return arr;
    }
    
    var results = count();
    var f1 = results[0];
    var f2 = results[1];
    var f3 = results[2];
    
    //然而f1(),f2(),f2()的结果并不是1,4,9,而全部是16

    原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了4,因此最终结果为16。

    如果一定要引用循环变量,需要再创建一个函数,用该函数的参数绑定当前循环变量的值:
    function count() {
        var arr = [];
        for (var i=1; i<=3; i++) {
            arr.push((function (n) {
                return function () {
                    return n * n;
                }
            })(i));
        }
        return arr;
    }
    
    var results = count();
    var f1 = results[0];
    var f2 = results[1];
    var f3 = results[2];
    
    f1(); // 1
    f2(); // 4
    f3(); // 9
    这里用到了一个语法 “创建一个匿名函数并立即执行”:
    (function (x) {
        return x * x;
    })(3); // 9
    //由于JavaScript语法解析的问题,会报SyntaxError错误,因此需要用括号把整个函数定义括起来

    3、闭包的意义

    上面我们讲到,闭包相当于把传参后的函数进行了保存但是并不会立刻执行,你要调用返回的这个函数才会执行,所以说闭包的意义只是在于延迟执行函数吗?当然不完全是这样,还有其他很多功能。

    在例如Java中,我们要封装一个私有变量,只需要加上private关键字就可以了,可是在JS中,我们也想要封装一个私有变量,怎么办?利用闭包。
    //e.g.创建一个计数器
    function create_counter(initial) {
        var x = initial || 0;
        return {
            inc: function () {
                x += 1;
                return x;
            }
        }
    }

    闭包中携带了局部变量x,但是当你使用该函数时,你实际上是无法访问到变量x的,即实际上这个函数的状态完全被隐藏了:
    var c1 = create_counter();
    c1.inc(); // 1
    c1.inc(); // 2
    c1.inc(); // 3
    
    var c2 = create_counter(10);
    c2.inc(); // 11
    c2.inc(); // 12
    c2.inc(); // 13

    闭包还可以创建新函数,例如把多参数的函数变成单参数的函数。例如,要计算x的y次方可以用Math.pow(x, y)函数,不过考虑到经常计算x平方或x立方,我们可以利用闭包创建新的函数pow2和pow3:
    function make_pow(n) {
        return function (x) {
            return Math.pow(x, n);
        }
    }
    
    // 创建两个新函数:
    var pow2 = make_pow(2);
    var pow3 = make_pow(3);
    
    pow2(5); // 25
    pow3(7); // 343


  • 相关阅读:
    js window对象属相和方法相关整理资料
    js中把字符串转换成number格式方法
    oracle中CAST函数使用简介【转】
    Oracle使用SQL语句修改字段类型
    @GeneratorValue与@GenericGenerator注解使用心得
    @Column 注解详情
    Spring中的注入方式 和使用的注解 详解
    maven教程
    wxpyhon 对话框
    wxpython 按钮等事件的触发
  • 原文地址:https://www.cnblogs.com/deng-cc/p/6622610.html
Copyright © 2011-2022 走看看