zoukankan      html  css  js  c++  java
  • JavaScript的闭包

    1. 什么是闭包
    通俗地讲,JavaScript 中每个的函数都是一个闭包,但通常意义上嵌套的函数更能够体现出闭包的特性,请看下面这个例子:
    var generateClosure = function() {
    var count = 0;
    var get = function() {
    count ++;
    return count;
    };
    return get;
    };
    var counter = generateClosure();
    console.log(counter()); // 输出 1
    console.log(counter()); // 输出 2
    console.log(counter()); // 输出 3

    现象:

    这段代码中,generateClosure() 函数中有一个局部变量count,初值为 0。
    还有一个叫做 get 的函数,get 将其父作用域,也就是 generateClosure() 函数中的 count 变量增加 1,并返回 count 的值。generateClosure() 的返回值是 get 函数。
    在外部我们通过 counter 变量调用了 generateClosure() 函数并获取了它的返回值,也就是 get 函数,接下来反复调用几次 counter(),我们发现每次返回的值都递增了 1。
     
    分析:
    让我们看看上面的例子有什么特点,按照通常命令式编程思维的理解,count 是generateClosure 函数内部的变量,它的生命周期就是 generateClosure 被调用的时期,当 generateClosure 从调用栈中返回时,count 变量申请的空间也就被释放。
    问题是,在 generateClosure() 调用结束后,counter() 却引用了“已经释放了的” count变量,而且非但没有出错,反而每次调用 counter() 时还修改并返回了 count。
    这是怎么回事呢?
    这正是所谓闭包的特性。当一个函数返回它内部定义的一个函数时,就产生了一个闭包,闭包不但包括被返回的函数,还包括这个函数的定义环境。
    上面例子中,当函数generateClosure() 的内部函数 get 被一个外部变量 counter 引用时,counter 和generateClosure() 的局部变量就是一个闭包。
    如果还不够清晰,下面这个例子可以帮助你理解:
    var generateClosure = function() {
    var count = 0;
    var get = function() {
    count ++;
    return count;
    };
    return get;
    };
    var counter1 = generateClosure();
    var counter2 = generateClosure();
    console.log(counter1()); // 输出 1
    console.log(counter2()); // 输出 1
    console.log(counter1()); // 输出 2
    console.log(counter1()); // 输出 3
    console.log(counter2()); // 输出 2
     
    上面这个例子解释了闭包是如何产生的:counter1 和 counter2 分别调用了 generate-Closure() 函数,生成了两个闭包的实例,它们内部引用的 count 变量分别属于各自的运行环境。
    我们可以理解为,在 generateClosure() 返回 get 函数时,私下将 get 可能引用到的 generateClosure() 函数的内部变量(也就是 count 变量)也返回了,并在内存中生成了一个副本,之后 generateClosure() 返回的函数的两个实例 counter1和 counter2 就是相互独立的了。
     
    html:
    <ul>
      <li id="a1">aa</li>
      <li id="a2">aa</li>
      <li id="a3">aa</li>
    </ul>
     
    js:
    var lists = document.getElementsByTagName("li");
        for(var i=0; i<lists.length; i++){
            //i最后等于3 
            //想办法保存住i的值=>想到闭包
            function saveI(i){
                lists[i].onclick = function(){
                  alert(i)
                }
            }
            
            saveI(i);
        } 

     js:

    var lists = document.getElementsByTagName("li");
    for(var i=0; i<lists.length; i++){
            lists[i].onclick = function(){
                //这里this的指向是没问题的 只是i的值不能保留
                alert(this.getAttribute('id'))
            }
    } 
     
    2. 闭包的用途
    嵌套的回调函数
    闭包有两个主要用途:
    (1)是实现嵌套的回调函数
    (2)是隐藏对象的细节
    JavaScript通过约定在所有私有属性前加上下划线(例如_myPrivateProp)
     
     
  • 相关阅读:
    2-括号配对问题
    14-会场安排问题
    106-背包问题
    12-喷水装置
    HDU-5170
    HDU-1002
    贪吃蛇
    frame与bounds的区别
    MAC下Android的Eclipse开发环境的搭建
    有些人脸上太多的笑是因为他们心中有太多的泪
  • 原文地址:https://www.cnblogs.com/zqzjs/p/5090277.html
Copyright © 2011-2022 走看看