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


  • 相关阅读:
    python线程与进程手记
    3.08课·········switch case及if else嵌套(日期格式)
    3.07课·········if分支语句
    3.06课·········C#语言基础
    3.05课·········进制转换
    Oracle profile 使用技巧
    sys用户密码丢失找回密码的步骤和命令
    oracle帐号scott被锁定如何解锁
    SQL中哪些情况会引起全表扫描
    Oracle创建用户、角色、授权、建表
  • 原文地址:https://www.cnblogs.com/deng-cc/p/6622610.html
Copyright © 2011-2022 走看看