天天看點

第66天:閉包的原理和函數傳參

一、閉包的原理

在程式語言中,所謂閉包,是指文法域位于某個特定的區域,具有持續參照(讀寫)位于該區域内自身範圍之外的執行域上的非持久型變量值能力的段落。這些外部執行域的非持久型變量神奇地保留他們在閉包最初定義(或建立)時的值。

白話:  我們可以用一個函數 去通路 另外一個函數的内部變量的方式就是閉包。

測試題

 function outerFun()

{

  var a=0;

 function innerFun()

 {

a++;

 alert(a);

}

 return innerFun;  //注意這裡 不加()

var obj=outerFun();//必須加()

obj();  obj();  

var obj2=outerFun();

 obj2();  obj2();  

 結果是 :  1  2  1  2

閉包的優點 :

優點:不産生全局變量,實作屬性私有化。

缺點:閉包中的資料會常駐記憶體,在不用的時候要删掉否則會導緻記憶體溢出。

二、閉包的函數傳參

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>閉包的函數傳參</title>
 6     <style>
 7         div{
 8             width: 100px;
 9             height: 100px;
10             position: absolute;
11             left:0;
12             background-color: yellow;
13         }
14     </style>
15 </head>
16 <body>
17 <button id="btn1">右走</button>
18 <button id="btn2">左走</button>
19 <div id="box"></div>
20 </body>
21 </html>
22 <script>
23     /*//閉包原理
24     function outFun(){
25         var num=10;
26         function inFun(){
27             console.log(num);
28         }
29         return inFun;//傳回函數體 不帶括号
30     }
31     var obj=outFun();//調用函數
32     obj();//傳回函數值*/
33 
34     //函數傳參
35     /*function Fun(x){
36         return function(y){
37             console.log(x+y);
38         }
39     }
40     var obj=Fun(4);//把4傳給x  obj=function(){console.log(x)}
41     obj();// NaN
42     obj(2);//6*/
43 
44 
45     var btn1=document.getElementById("btn1");
46     var btn2=document.getElementById("btn2");
47     var box=document.getElementById("box");
48 
49     function move(speed){
50         return function(){
51             box.style.left=box.offsetLeft+speed+"px";
52         }
53     }
54     btn1.onclick=move(5);
55     btn2.onclick=move(-5);
56 </script>      

三、執行個體

1、閉包版tab切換

1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>閉包版tab欄切換</title>
  6     <style>
  7         *{
  8             margin: 0;
  9             padding: 0;
 10         }
 11         .box{
 12             width: 405px;
 13             height: 400px;
 14             border:1px solid #c1c1c1;
 15             margin: 100px auto;
 16             /*overflow: hidden;*/
 17         }
 18         .mt span{
 19             display: inline-block;
 20             width: 80px;
 21             height: 30px;
 22             text-align: center;
 23             line-height: 30px;
 24             background-color: #ff4400;
 25             border-right: 1px solid #c1c1c1;
 26             cursor: pointer;
 27         }
 28         .mt .current{
 29             background-color: #3B90CD;
 30         }
 31         .mb li{
 32             width: 100%;
 33             height: 370px;
 34             background-color: #3B90CD;
 35             list-style: none;
 36             display: none;
 37         }
 38         .mb .show{
 39             display: block;
 40         }
 41     </style>
 42     <script>
 43         window.onload=function(){
 44             function tab(obj){
 45                 //擷取每個盒子的id
 46                 var target=document.getElementById(obj);
 47                 //擷取對應id下的标簽
 48                 var spans=target.getElementsByTagName("span");
 49                 var lis=target.getElementsByTagName("li");
 50                 for(var i=0;i<spans.length;i++) {
 51 
 52                     //function() {} ();立即執行函數
 53                     var timer=null;
 54                     spans[i].onmouseover = function (num) {//num 形參
 55                         return function () {
 56                             clearTimeout(timer);
 57                             timer = setTimeout(function () {
 58                                 for (var j = 0; j < spans.length; j++) {
 59                                     //清除所有的 類
 60                                     spans[j].className = "";
 61                                     lis[j].className = "";
 62                                 }
 63                                 //顯示目前點選的類
 64                                 spans[num].className = "current";
 65                                 lis[num].className = "show";//span和li對應起來
 66                             }, 300)
 67                         }
 68                         }(i);//i傳參
 69                     spans[i].onmouseout=function(){
 70                         clearTimeout(timer);
 71                     }
 72                 }
 73                 }
 74             tab("one");
 75             tab("two");
 76             tab("three");
 77         }
 78     </script>
 79 </head>
 80 <body>
 81 <div class="box" id="one">
 82     <div class="mt">
 83         <span class="current">新聞</span><span>體育</span><span>娛樂</span><span>科技</span><span>視訊</span>
 84     </div>
 85     <div class="mb">
 86         <ul>
 87             <li class="show">新聞子產品</li>
 88             <li>體育子產品</li>
 89             <li>娛樂子產品</li>
 90             <li>科技子產品</li>
 91             <li>視訊子產品</li>
 92         </ul>
 93     </div>
 94 </div>
 95 
 96 <div class="box" id="two">
 97     <div class="mt">
 98         <span class="current">新聞</span><span>體育</span><span>娛樂</span><span>科技</span><span>視訊</span>
 99     </div>
100     <div class="mb">
101         <ul>
102             <li class="show">新聞子產品</li>
103             <li>體育子產品</li>
104             <li>娛樂子產品</li>
105             <li>科技子產品</li>
106             <li>視訊子產品</li>
107         </ul>
108     </div>
109 </div>
110 
111 <div class="box" id="three">
112     <div class="mt">
113         <span class="current">新聞</span><span>體育</span><span>娛樂</span><span>科技</span><span>視訊</span>
114     </div>
115     <div class="mb">
116         <ul>
117             <li class="show">新聞子產品</li>
118             <li>體育子產品</li>
119             <li>娛樂子產品</li>
120             <li>科技子產品</li>
121             <li>視訊子產品</li>
122         </ul>
123     </div>
124 </div>
125 </body>
126 </html>      

2、閉包版螢幕縮放事件

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <div id="demo"></div>
 9 </body>
10 </html>
11 <script>
12     var num=0;
13     var demo=document.getElementById("demo");
14     window.onresize=throttle(function(){
15         demo.innerHTML=window.innerWidth||document.documentElement.clientWidth;
16         num++;
17         console.log(num);
18     },300);
19 
20     function throttle(fn,delay){//閉包  節流
21         var timer=null;
22         return function(){
23             clearTimeout(timer);
24             timer=setTimeout(fn,delay);//delay控制延遲時間
25         }
26     }
27 
28 </script>