最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS閉包可被利用的常見場景小結(jié)

 更新時間:2017年04月09日 14:00:46   投稿:mdxy-dxy  
閉包的一個通常的用法是為一個在某一函數(shù)執(zhí)行前先執(zhí)行的函數(shù)提供參數(shù)。例如,在web環(huán)境中,一個函數(shù)作為setTimeout函數(shù)調(diào)用的第一個參數(shù),是一種很常見的應(yīng)用

場景一:采用函數(shù)引用方式的setTimeout調(diào)用

閉包的一個通常的用法是為一個在某一函數(shù)執(zhí)行前先執(zhí)行的函數(shù)提供參數(shù)。例如,在web環(huán)境中,一個函數(shù)作為setTimeout函數(shù)調(diào)用的第一個參數(shù),是一種很常見的應(yīng)用。

setTimeout將要執(zhí)行的函數(shù)(或者一段JavaScript代碼,但這不是我們要討論的情況)作為它的第一個參數(shù),下一個參數(shù)是需要延遲執(zhí)行的時間。如果一段代碼想通過setTimeout來調(diào)用,那么它需要傳遞一個函數(shù)對象的引用來作為第一個參數(shù)。延遲的毫秒數(shù)作為第二個參數(shù),但這個函數(shù)對象的引用無法為將要被延遲執(zhí)行的對象提供參數(shù)。
但是,可以調(diào)用另一個函數(shù)來返回一個內(nèi)部函數(shù)的調(diào)用,將那個內(nèi)部函數(shù)對象的引用傳遞給setTimeout函數(shù)。內(nèi)部函數(shù)執(zhí)行時需要的參數(shù),在調(diào)用外部函數(shù)時傳遞給它。setTimeout在執(zhí)行內(nèi)部函數(shù)時無需傳遞參數(shù),因為內(nèi)部函數(shù)仍然能夠訪問外部函數(shù)調(diào)用時提供的參數(shù):

function callLater(paramA, paramB, paramC) {
      /*使用函數(shù)表達式創(chuàng)建并放回一個匿名內(nèi)部函數(shù)的引用*/
      return (function () {
        /*
        這個內(nèi)部函數(shù)將被setTimeout函數(shù)執(zhí)行;
        并且當它被執(zhí)行時,
        它能夠訪問并操作外部函數(shù)傳遞過來的參數(shù)
        */
        paramA[paramB] = paramC;
      });
    }

    /*
    調(diào)用這個函數(shù)將在它的執(zhí)行上下文中創(chuàng)建,并最終返回內(nèi)部函數(shù)對象的引用
    傳遞過來的參數(shù),內(nèi)部函數(shù)在最終被執(zhí)行時,將使用外部函數(shù)的參數(shù)
    返回的引用被賦予了一個變量
    */
    var funcRef = callLater(elStyle, "display", "none");
    /*調(diào)用setTimeout函數(shù),傳遞內(nèi)部函數(shù)的引用作為第一個參數(shù)*/
    hideMenu = setTimeout(funcRef, 500);

場景二:將函數(shù)關(guān)聯(lián)到對象的實例方法

有很多這樣的場景:需要分配一個函數(shù)對象的引用,以便在未來的某個時間執(zhí)行該函數(shù)。那么閉包對于為這個將要執(zhí)行的函數(shù)提供引用會非常有幫助。因為該函數(shù)可能直到執(zhí)行時才能夠被訪問。

有一個例子就是,一個javascript對象被封裝用來參與一個特定DOM元素的交互。它有doOnClick、doMouseOver以及doMouseOut方法。并且想在DOM元素上對應(yīng)的事件被觸發(fā)時執(zhí)行這些方法。但是,可能會有關(guān)聯(lián)著DOM元素的任意數(shù)量的javascript對象被創(chuàng)建,并且單個的實例并不知道那些實例化它們的代碼將如何處理它們。對象實例不知道怎樣去“全局”地引用它們自己,因為它們不知道哪個全局變量(如果存在)的引用將被分配給它們。

所以,問題是執(zhí)行一個與特定javascript對象實例關(guān)聯(lián)的事件處理函數(shù),并且知道調(diào)用那個對象的哪個方法。
接下來的一個例子,在有元素事件處理的對象實例的關(guān)聯(lián)函數(shù)上使用一個簡單的閉包。通過傳遞event對象以及要關(guān)聯(lián)元素的一個引用,為事件處理器分配不同的對象實例方法以供調(diào)用。

/*
    一個給對象實例關(guān)聯(lián)一個事件處理器的普通方法,
    返回的內(nèi)部函數(shù)被作為事件的處理器,
    對象實例被作為obj參數(shù),對象上將要被調(diào)用的方法名稱被作為第二個參數(shù)
    */
    function associateObjWithEvent(obj, methodName) {
      /*返回的內(nèi)部函數(shù)被用來作為一個DOM元素的事件處理器*/
      return (function (e) {
        /*
        事件對象在DOM標準的瀏覽器中將被轉(zhuǎn)換為e參數(shù),
        如果沒有傳遞參數(shù)給事件處理內(nèi)部函數(shù),將統(tǒng)一處理成IE的事件對象
        */
        e = e || window.event;
        /*
        事件處理器調(diào)用obj對象上的以methodName字符串標識的方法
        并傳遞兩個對象:通用的事件對象,事件處理器被訂閱的元素的引用
        這里this參數(shù)能夠使用,因為內(nèi)部函數(shù)已經(jīng)被執(zhí)行作為事件處理器所在元素的一個方法
        */
        return obj[methodName](e, this);
      });
    }

    /*
    這個構(gòu)造器函數(shù),通過將元素的ID作為字符串參數(shù)傳遞進來,
    來創(chuàng)建將自身關(guān)聯(lián)到DOM元素上的對象,
    對象實例想在對應(yīng)的元素觸發(fā)onclick、onmouseover、onmouseout事件時
    對應(yīng)的方法被調(diào)用。
    */
    function DhtmlObject(elementId) {
      /*
      調(diào)用一個方法來獲得一個DOM元素的引用
      如果沒有找到,則為null
      */
      var el = getElementWith(elementId);
      /*
      因為if語句塊,el變量的值在內(nèi)部進行了類型轉(zhuǎn)換,變成了boolean類型
      所以當它指向一個對象,結(jié)果就為true,如果為null則為false
      */
      if (el) {
        /*
        為了給元素指定一個事件處理函數(shù),調(diào)用了associateObjWithEvent函數(shù),
        利用它自己(this關(guān)鍵字)作為被調(diào)用方法的對象,并且提供方法名稱
        */
        el.onclick = associateObjWithEvent(this, "doOnClick");
        el.onmouseover = associateObjWithEvent(this, "doOnMouseOver");
        el.onmouseout = associateObjWithEvent(this, "doOnMouseOut");
      }
    }

    DhtmlObject.prototype.doOnClick = function (event, element) {
      //doOnClick body
    }
    DhtmlObject.prototype.doMouseOver = function (event, element) {
      //doMouseOver body
    }

    DhtmlObject.prototype.doMouseOut = function (event, element) {
      //doMouseOut body
    }

任何DhtmlObject的實例都能夠?qū)⑺鼈冏陨黻P(guān)聯(lián)到它們感興趣的DOM元素上去,不需要去擔心這些元素將被其他的代碼怎么處理,以及被全局命名空間“污染”或者與其他的DhtmlObject的實例產(chǎn)生沖突。

場景三:封裝相關(guān)的功能集

閉包可以創(chuàng)建額外的scope,這可以被用來組合相關(guān)的或有依賴性的代碼。用這種方式可以最大限度地減少代碼干擾的危害。假設(shè),一個函數(shù)被用來創(chuàng)建一個字符串并且避免重復(fù)串聯(lián)的操作(比如創(chuàng)建一系列的中間字符串)。一個想法是,用一個數(shù)組來順序存儲字符串的一部分,然后使用Array.prototype.join方法輸出結(jié)果(使用一個空字符串作為它的參數(shù))。數(shù)組將扮演著輸出緩沖區(qū)的角色,但局部定義它又將會導(dǎo)致它在函數(shù)的每次執(zhí)行時再次創(chuàng)建。如果這個數(shù)組只是作為唯一的變量被分配給每一個函數(shù)調(diào)用,這將會有點小題大做。

一個解決方案是將數(shù)組提升為全局變量,讓它不需要被再次創(chuàng)建也能夠再次使用。但結(jié)果并不是想的那么簡單,另外,一個全局變量關(guān)聯(lián)這使用緩沖數(shù)組的函數(shù),那將會有第二個全局屬性(函數(shù)本身也是window對象的屬性)關(guān)聯(lián)這個數(shù)組,這將讓代碼失去一定的可控性。因為如果將它使用在其他地方。這段代碼的創(chuàng)建者不得不記住包含函數(shù)的定義以及數(shù)組的定義邏輯。它也使得代碼不那么容易與其他代碼整合,因為將從原來只需要確定函數(shù)名是否在全局命名空間中唯一,變成有必要確定和該函數(shù)關(guān)聯(lián)的數(shù)組的名稱是否在全局命名空間中保持唯一。

一個閉包可以讓緩沖數(shù)組關(guān)聯(lián)(干凈地包含)它依賴的函數(shù),并且同時保持緩沖數(shù)組的屬性名稱,像被分配在全局空間中一樣,同時能夠避免名稱沖突以及代碼交互干擾的危險。

這里有一招就是通過執(zhí)行一個內(nèi)聯(lián)的函數(shù)表達式創(chuàng)建一個額外的執(zhí)行上下文,讓那個函數(shù)表達式返回一個內(nèi)聯(lián)的函數(shù),該函數(shù)被外部代碼使用。緩沖數(shù)組被定義在內(nèi)聯(lián)執(zhí)行的函數(shù)表達式中,作為一個局部變量。它僅被調(diào)用一次,所以該數(shù)組只被創(chuàng)建一次。但是對于依賴它的函數(shù)來說該數(shù)組是一直可訪問的,并且可被重用的。

接一下的代碼創(chuàng)建了一個函數(shù),將返回一個HTML字符串,其中的一部分是不變的,但那些不變的字符串需要被穿插進作為參數(shù)傳遞進來的變量中。

一個內(nèi)聯(lián)執(zhí)行的函數(shù)表達式返回了內(nèi)部函數(shù)對象的一個引用。并且分配了一個全局變量,讓它可以被作為一個全局函數(shù)來調(diào)用。而緩沖數(shù)組作為一個局部變量被定義在外部函數(shù)表達式中。它沒有被擴展到全局命名空間中,并且無論函數(shù)什么時候使用它都不需要被再次創(chuàng)建。

/*
     定義一個全局變量:getImgInPositionedDivHtml
     被賦予對外部函數(shù)表達式一次調(diào)用返回的一個內(nèi)部函數(shù)表達式

     內(nèi)部函數(shù)返回了一個HTML字符串,代表一個絕對定位的DIV
     包裹這一個IMG元素,而所有的變量值都被作為函數(shù)調(diào)用的參數(shù)
    */
    var getImgInPositionedDivHtml = (function () {
      /*
      buffAr 數(shù)組被定義在外部函數(shù)表達式中,作為一個局部變量
      它只被創(chuàng)建一次。數(shù)組的唯一實例對內(nèi)部函數(shù)是可見的,
      所以它可以被用于每一次的內(nèi)部函數(shù)執(zhí)行

      空字符串僅僅被用來作為一個占位符,它將被內(nèi)部函數(shù)的參數(shù)代替
      */
      var buffAr = [
         '<div id="',
        '',  //index 1, DIV ID attribute
        '" style="position:absolute;top:',
        '',  //index 3, DIV top position
        'px;left:',
        '',  //index 5, DIV left position
        'px;width:',
        '',  //index 7, DIV width
        'px;height:',
        '',  //index 9, DIV height
        'px;overflow:hidden;\"><img src=\"',
        '',  //index 11, IMG URL
        '\" width=\"',
        '',  //index 13, IMG width
        '\" height=\"',
        '',  //index 15, IMG height
        '\" alt=\"',
        '',  //index 17, IMG alt text
        '\"><\/div>'
      ];

      /*
      返回一個內(nèi)部函數(shù)對象,他是函數(shù)表達式執(zhí)行返回的結(jié)果
      */
      return (function (url, id, width, height, top, left, altText) {
        /*
        分配各種參數(shù)給對應(yīng)的數(shù)組元素
        */
        buffAr[1] = id;
        buffAr[3] = top;
        buffAr[5] = left;
        buffAr[13] = (buffAr[7] = width);
        buffAr[15] = (buffAr[9] = height);
        buffAr[11] = url;
        buffAr[17] = altText;

        /*
        返回連接每個元素后創(chuàng)建的字符串
        */
        return buffAr.join('');
      });
    })();

如果一個函數(shù)依賴另一個或幾個函數(shù),但那些其他的函數(shù)并不期望與任何其他的代碼產(chǎn)生交互。那么這個簡單的技巧(使用一個對外公開的函數(shù)來擴展那些函數(shù))就可以被用來組織那些函數(shù)。

相關(guān)文章

  • javaScript使用EL表達式的幾種方式

    javaScript使用EL表達式的幾種方式

    這篇文章主要介紹了javaScript如何使用EL表達式,有哪幾種不錯的方式,需要的朋友可以參考下
    2014-05-05
  • JS獲取年月日時分秒的方法分析

    JS獲取年月日時分秒的方法分析

    這篇文章主要介紹了JS獲取年月日時分秒的方法,結(jié)合實例形式分析了JS獲取具體時間的常犯錯誤與相應(yīng)解決方法,需要的朋友可以參考下
    2016-11-11
  • 使用D3.js創(chuàng)建物流地圖的示例代碼

    使用D3.js創(chuàng)建物流地圖的示例代碼

    本篇文章主要介紹了使用D3.js創(chuàng)建物流地圖的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 通過 Dom 方法提高 innerHTML 性能

    通過 Dom 方法提高 innerHTML 性能

    此方法大大提高了 innerHTML 在 Firefox 和 Safari 上的性能。replaceHtml() 在 Firefox 2.0.0.6 里 destroy 與 replace 的速度各快了 473 倍以及 50 倍。而在 Safari 3.0.3 beta 上則是 create 100 倍,replace 50 倍。
    2008-03-03
  • Openlayers實現(xiàn)長度測量的方法

    Openlayers實現(xiàn)長度測量的方法

    在Openlayers中,使用ol/sphere模塊的getDistance函數(shù)可以計算兩點間的大圓距離,繪制線路時,通過監(jiān)聽繪制事件和幾何對象的變化,可實時更新距離,同時getLength函數(shù)幫助獲取整條線路的長度,這些功能主要用于地理信息系統(tǒng)中的距離測量和地圖制作
    2024-11-11
  • JavaScript利用虛擬列表實現(xiàn)高性能渲染數(shù)據(jù)詳解

    JavaScript利用虛擬列表實現(xiàn)高性能渲染數(shù)據(jù)詳解

    在前文中我們提到可以使用時間分片的方式來對長列表進行渲染,但這種方式更適用于列表項的DOM結(jié)構(gòu)十分簡單的情況,所以本文來講講如何使用虛擬列表的方式,來同時加載大量數(shù)據(jù)吧
    2023-05-05
  • 使用原生js編寫一個簡單的框選功能方法

    使用原生js編寫一個簡單的框選功能方法

    這篇文章主要介紹了使用原生js編寫一個簡單的框選功能方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2019-05-05
  • SharedWorker?多頁面相互通信示例詳解

    SharedWorker?多頁面相互通信示例詳解

    這篇文章主要為大家介紹了SharedWorker?多頁面相互通信示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • JavaScript兩種axios取消請求方式小結(jié)

    JavaScript兩種axios取消請求方式小結(jié)

    本文主要介紹了JavaScript兩種axios取消請求方式小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2023-03-03
  • js中浮點型運算BUG的解決方法說明

    js中浮點型運算BUG的解決方法說明

    本篇文章主要是對js中浮點型運算BUG的解決方法進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01

最新評論

皋兰县| 若尔盖县| 大新县| 舒兰市| 沧州市| 沾益县| 临高县| 华安县| 乌审旗| 称多县| 井研县| 建昌县| 余庆县| 长丰县| 龙口市| 神木县| 库伦旗| 临泽县| 绥棱县| 临澧县| 大悟县| 甘德县| 深泽县| 南召县| 莱芜市| 汉中市| 宽甸| 达拉特旗| 广汉市| 鲁甸县| 都江堰市| 贡嘎县| 永州市| 沐川县| 合山市| 罗山县| 开化县| 临汾市| 西贡区| 正安县| 肥城市|