透過Extjs學習JavaScript---閉包篇

目錄

1、 前言
4、 總結

1、前言

JavaScript設計得最出色的就是它的函數的實現,它幾乎接近於完美。咱們如今現就來介紹它其中一個功能「閉包」。咱們能夠利用閉包「保存變量生命週期」和「屏蔽變量」的特性優雅地完成一些強大的功能。後面我還會介紹在ExtJS中是如何使用這種特性的。數組

2、基礎講解

咱們能夠利用「閉包」功能來實現隱藏或公開對象的變量和方法。服務器

測試代碼以下閉包

 1 var bufferObj = (function createFun(fn, interval, scope) {
 2     var isExec = 1;//被閉包的變量,外界不能直接訪問
 3     return {//公開set,和exec方法
 4         set : function(data) {
 5             isExec = data;
 6         },
 7         exec : function(fn) {
 8             if (isExec) {//讀取閉包的變量
 9                 console.log("函數能夠執行");
10                 fn();
11             } else {
12                 console.log("函數不能執行");
13             }
14         }
15     };
16 })();

注意咱們把整個函數用括號包住,並在最後一行加了"()",這樣寫法的意思是立刻執行函數,並返回告終果值。這樣咱們的變量「bufferObj」對象就是帶有公開的set和exec方法和私有變量「isExec」。我不能直接訪問到「isExec」這個變量,這就是咱們使用閉包的結果,將一些變量或方法優雅的變成私有,很好的控制了變量的做用域。app

3、知識應用

上節初步的說明了閉包的寫法和功能,看似功能不過如此,其實否則。下面咱們來看看ExtJs是如何使用閉包功能的,但願能夠給你們在使用閉包有更多的啓發。這也是學習JS這門語言有興趣的地方,是把一個簡簡單單的知識點寫出多種花樣。函數

下面的代碼是extjs中「Ext.Function」類中的「createBuffered」方法,主要功能就是生成「帶有延遲功能的函數」。我爲了簡化「Ext.Function」類的上下文,並把代碼標上的漢語解釋方便講解。學習

Ext.Function 代碼以下:測試

 1 var Ext = {};
 2 Ext.Function = {
 3     /**
 4      * 返回帶有延遲功能的函數,若是在延遲的時間內再次調用該函數,重置緩衝時間
 5      * @param {Function} fn 須要被延遲的方法
 6      * @param {Number} buffer 延遲時間(毫秒)
 7      * @param {Object} [scope=this] 傳入方法的做用域
 8      * @param {Array} [args] 方法參數
 9      * @return {Function} 返回帶有緩衝功能的函數
10      */
11     createBuffered: function(fn, buffer, scope, args) {
12         var timerId;//計時器ID
13 
14         return function() {
15             var callArgs = args || Array.prototype.slice.call(arguments, 0),//將「arguments」類型轉成數組類型
16                 me = scope || this;//若是沒有傳入「scope」參數就全用當前上下文的"this"爲做用域
17 
18             if (timerId) {//若是有計時器,就取消以前的計時器
19                 clearTimeout(timerId);
20             }
21 
22             timerId = setTimeout(function(){//重置緩衝時間
23                 fn.apply(me, callArgs);//在相應的做用域上執行方法
24             }, buffer);
25         };
26     }
27 };

在上述代碼中把變量「timerId」閉包在對象內,只返回了一個帶有緩衝功能的方法,該返回方法主要是判斷函數在緩衝期內是否被重複調用,若是在緩衝期內被調用就重置計時器。this

在代碼中有三個知識點:spa

1.  15行中「Array.prototype.slice.call(arguments, 0)」這句意思是把arguments參數類型轉成數組類型,方便第23行的「apply」調用。(若是不知道arguments是什麼意思的同窗就自行面壁思過吧,哈哈哈。)prototype

2.  16行中"me = scope || this" ,是一個if判斷取巧的寫法。整句的意思是,當「scope」爲「空」或「假」時就把「this」返回給「me」變量。

3.  18行中的「timerId」變量因爲是被閉包,他的「生命期」被延長了,不會隨着返回函數的運行結束而結束,因此每次調用返回函數時,均可以保留以前的「timerId」值。

使用代碼以下:

 1 var run = function(data) {
 2     alert("函數運行成功");
 3     alert("入參爲:" + data);
 4 };
 5 var bufferFn = Ext.Function.createBuffered(run, 3000);
 6 bufferFn("JavaScript1");//不會被執行,由於後一個函數在緩衝期3秒內調用,把這當前的函數取消了
 7 bufferFn("JavaScript2");//不會被執行,由於後一個函數在緩衝期3秒內調用,把這當前的函數取消了
 8 bufferFn("JavaScript3");//會被執行,由於後一個函數沒有在緩衝期3秒內調用,因此該函數會執行
 9 
10 setTimeout(function() {//間隔4秒
11     bufferFn("JavaScript4");//會被執行,由於後面沒有重複調用了
12 }, 4000);

 在上述代碼第5行,就是經過「Ext.Function.createBuffered」生成了一個帶有緩衝功能的函數「bufferFn」,若是咱們在3秒的緩衝期內重複調用就不會重複執行函數。

4、總結

  1. 筆者的案例代碼是取自於ExtJs,可能有些很差理解,可是當你看懂了,就能感受到JS這門語言的巧妙。
  2. 文本只是經過介紹閉包的方法,進而介紹下ExtJs的源碼,使咱們擼代碼的水平有所提高。

5、常見問題

  • 問:有的人會問這建立延遲函數有什麼用?感受在實際狀況下用不到? 
    答:筆者可不這麼認爲,我在作項目中就經常用到這種方法。當咱們要對一個輸入框發生內容改變時,進行AJAX查詢。但又不想每輸入一個字就進行一次查詢,由於這樣很是的消耗服務器資源。較好的解決方案是設置一個輸入緩衝期,在這個輸入緩衝期內輸入字母不進行查詢,等過了緩衝期在對以前輸入過的全部字母進行查詢,因此咱們須要一個「帶有延遲緩衝功能」的函數。
  • 問:arguments這究竟是什麼? 
    答:好吧,詳細請訪問http://www.w3school.com.cn/js/pro_js_functions_arguments_object.asp,arguments是一個特殊的對象,相似於數組,但不徹底是數組,因此要用「Array.prototype.slice.call(arguments, 0)」方法轉成常規的數組。
相關文章
相關標籤/搜索