闭包——之初理解

闭包,是javascript中的一个概念,对于初学者很难理解抽象的概念,看了很多大牛们的解释,也是似懂非懂的,今天在知乎上看到很多“大神”们对“闭包”做了又一番解释,在其中也学到了不少,下面就来说下自己对闭包的理解吧。 

闭——外面的变量看不到里面的,包——可以对内部变量操作,返回一个'包';

闭包并不是私有的,闭的意思不是封闭“内部状态”,而是封闭“外部状态” ;
用知乎上“大神”更简洁的一句话总结:闭包就是一个有记忆的函数;
在《js高级程序设计》里面的解释:闭包是指有权访问另一个函数作用域中的变量函数。

1.看一个简单的闭包的例子:
function A(){
    function B(){
       console.log("Hello world!");
    }
    return B;
}
var c = A();
c();//Hello world!

最常见的闭包,就是在一个函数内部再创建一个函数;也是最简单的闭包,有了上面简单的概念认识,我们分析一下闭包函数和普通函数有什么不同的地方:

上面代码翻译成自然语言如下:

(1)定义了一个普通函数A

(2)在A中定义了普通函数B

(3)在A中返回B(确切的讲,在A中返回B的引用)

(4)执行A(),把A的返回结果赋值给变量 c

(5)执行 c()

把这5步操作总结成一句扯淡的话就是:

函数A的内部函数B被函数A外的一个变量 c 引用

把这句扯淡的话再加工一下就变成了闭包的定义:

当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。 

2.demo是理解抽象东西的最好方法,下面来看一下闭包怎么用,又会在哪些地方能用到它呢。

(1.)改变字体的大小(点击不同的字体,改变body字体的大小)

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <script>
            window.onload = function() {
                         function ftsize(sizes){
                         return function(){
                               document.body.style.fontSize=sizes+"px";
                            } 
                      }
                      var fontsize12=ftsize(12); 
                      var fontsize14=ftsize(14); 
                      var fontsize16=ftsize(22); 
                      document.getElementById("font-size12").onclick=fontsize12;
                      document.getElementById("font-size14").onclick=fontsize14;
                      document.getElementById("font-size22").onclick=fontsize22; 
            }
        </script>
    </head>

    <body>
        <a href="#" id="font-size12">12号字体</a>
        <a href="#" id="font-size14">14号字体</a>
        <a href="#" id="font-size22">22号字体</a> 
    </body> 
</html>
View Code

(2.)用户小调查,当文本框获取焦点时提示用户输入正确的内容 

<!DOCTYPE html>
<html> 
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script>
            window.onload = function() { 
                function showHelp(help) {
                    document.getElementById('help').innerHTML = help;
                } 
                function makeHelpCallback(help) {
                    return function() {
                        showHelp(help);
                    };
                } 
                function setupHelp() {
                    var helpText = [
                        {'id': 'email','help': '填写你正确的email地址'},
                        {'id': 'name', 'help': '填写你的真实姓名'    }, 
                        {'id': 'age', 'help': '你的年龄必须大于16岁'}
                    ];
                    for (var i = 0; i < helpText.length; i++) {
                        var item = helpText[i];
                        document.getElementById(item.id).onfocus =
                            makeHelpCallback(item.help);
                    }
                }
                setupHelp();
            }
        </script>
    </head> 
    <body>         
        <p id="help">用户小调查</p>
        <p>邮箱: <input type="text" id="email" name="email"></p>
        <p>姓名: <input type="text" id="name" name="name"></p>
        <p>年龄: <input type="text" id="age" name="age"></p>
    </body> 
</html>
View Code

(3.)点击不同的li时弹出对应的index  

        我们可以想到的一种方法就是用JQ循环每一个li获取下标代码如下:        

<!DOCTYPE html>
<html> 
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="js/jquery.js"></script>
        <script> 
            $(function() {
                $("li").each(function() {
                    $(this).click(function() {
                        alert($(this).index());
                    })
                })
            })
        </script>
    </head> 
    <body>
        <ul>
            <li>aaaaaa</li>
            <li>bbbbbb</li>
            <li>ccccccc</li>
            <li>dddddd</li>
        </ul>
    </body> 
</html>

 我们不用JQ,用JS来实现呢代码如下:

 <script>
    window.onload = function() {
         var nodes = document.getElementsByTagName("li");
         for (i = 0; i < nodes.length; i += 1) {
                   nodes[i].onclick = function() {
                   alert(i); //值全是4
                };
             }
      }
</script>  

 值全为4,这是为什么呢,当事件(li被点击)被执行时,外层函数的for循环早已结束,所以索引i已经变成4,因此我们点击后会返回里层函数变量对象指向的值i也就是4;解决这个问题我们这时又可以用到闭包了

代码如下: 

function alertindex(nodes) {
         var helper = function(a) {
                 return function() {
                        alert(a);
                    };
             };
             var i = 0;
             for (i = 0; i < nodes.length; i++) {
                    nodes[i].onclick = h elper(i);
              }
          };
         alertindex(document.getElementsByTagName("li"));
}

i是alertindex中的一个变量,它的值在helper中被引用,当for循环一次函数helper就被调用执行一次,i的值就在原来的基础上累加1。因此,alertindex中的i一直保存在内存中。即得到我们想要的结果。 

这就是闭包的作用,有时候我们需要一个模块中定义一个变量:希望这个变量一直保存在内存中但又不会“污染”全局的变量,这个时候,我们就可以用闭包来定义这个模块。 

总结

有了简单的理解和应用之后,在以后的更多的实践应用中会对闭包有越来越多越深的理解。

参考:http://www.codeceo.com/article/javascript-closures.html(让你分分钟学会 JavaScript 闭包

        https://www.zhihu.com/question/31383111(怎么更好的理解闭包)

        https://www.zhihu.com/question/28849447(到底该如何理解闭包)

        https://www.zhihu.com/question/19554716(JavaScript 里的闭包是什么?应用场景有哪些?)

原文地址:https://www.cnblogs.com/hfxm/p/5556530.html