• 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


  • 相关阅读:
    Bootstrap3.0学习第八轮(工具Class)
    dependencies与dependencyManagement的区别
    灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断
    Linux平台安装MongoDB
    ubuntu 该软件包现在的状态极为不妥 error
    oracle vm突然黑屏了
    Oracle VM VirtualBox各种显示模式切换 热键
    where后一个条件和多个条件的查询速度
    String特殊值的判断方式
    将中文标点符号替换成英文标点符号
  • 原文地址:https://www.cnblogs.com/deng-cc/p/6622610.html
Copyright © 2020-2023  润新知