成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

JS閉包可被利用的常見(jiàn)場(chǎng)景有哪些

這篇文章給大家分享的是有關(guān)JS閉包可被利用的常見(jiàn)場(chǎng)景有哪些的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

成都創(chuàng)新互聯(lián)是一家專注網(wǎng)站建設(shè)、網(wǎng)絡(luò)營(yíng)銷策劃、小程序定制開(kāi)發(fā)、電子商務(wù)建設(shè)、網(wǎng)絡(luò)推廣、移動(dòng)互聯(lián)開(kāi)發(fā)、研究、服務(wù)為一體的技術(shù)型公司。公司成立十多年以來(lái),已經(jīng)為成百上千成都辦公空間設(shè)計(jì)各業(yè)的企業(yè)公司提供互聯(lián)網(wǎng)服務(wù)。現(xiàn)在,服務(wù)的成百上千客戶與我們一路同行,見(jiàn)證我們的成長(zhǎng);未來(lái),我們一起分享成功的喜悅。

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

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

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

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

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

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

有很多這樣的場(chǎng)景:需要分配一個(gè)函數(shù)對(duì)象的引用,以便在未來(lái)的某個(gè)時(shí)間執(zhí)行該函數(shù)。那么閉包對(duì)于為這個(gè)將要執(zhí)行的函數(shù)提供引用會(huì)非常有幫助。因?yàn)樵摵瘮?shù)可能直到執(zhí)行時(shí)才能夠被訪問(wèn)。

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

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

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

    /*
    這個(gè)構(gòu)造器函數(shù),通過(guò)將元素的ID作為字符串參數(shù)傳遞進(jìn)來(lái),
    來(lái)創(chuàng)建將自身關(guān)聯(lián)到DOM元素上的對(duì)象,
    對(duì)象實(shí)例想在對(duì)應(yīng)的元素觸發(fā)onclick、onmouseover、onmouseout事件時(shí)
    對(duì)應(yīng)的方法被調(diào)用。
    */
    function DhtmlObject(elementId) {
      /*
      調(diào)用一個(gè)方法來(lái)獲得一個(gè)DOM元素的引用
      如果沒(méi)有找到,則為null
      */
      var el = getElementWith(elementId);
      /*
      因?yàn)閕f語(yǔ)句塊,el變量的值在內(nèi)部進(jìn)行了類型轉(zhuǎn)換,變成了boolean類型
      所以當(dāng)它指向一個(gè)對(duì)象,結(jié)果就為true,如果為null則為false
      */
      if (el) {
        /*
        為了給元素指定一個(gè)事件處理函數(shù),調(diào)用了associateObjWithEvent函數(shù),
        利用它自己(this關(guān)鍵字)作為被調(diào)用方法的對(duì)象,并且提供方法名稱
        */
        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的實(shí)例都能夠?qū)⑺鼈冏陨黻P(guān)聯(lián)到它們感興趣的DOM元素上去,不需要去擔(dān)心這些元素將被其他的代碼怎么處理,以及被全局命名空間“污染”或者與其他的DhtmlObject的實(shí)例產(chǎn)生沖突。

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

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

一個(gè)解決方案是將數(shù)組提升為全局變量,讓它不需要被再次創(chuàng)建也能夠再次使用。但結(jié)果并不是想的那么簡(jiǎn)單,另外,一個(gè)全局變量關(guān)聯(lián)這使用緩沖數(shù)組的函數(shù),那將會(huì)有第二個(gè)全局屬性(函數(shù)本身也是window對(duì)象的屬性)關(guān)聯(lián)這個(gè)數(shù)組,這將讓代碼失去一定的可控性。因?yàn)槿绻麑⑺褂迷谄渌胤健_@段代碼的創(chuàng)建者不得不記住包含函數(shù)的定義以及數(shù)組的定義邏輯。它也使得代碼不那么容易與其他代碼整合,因?yàn)閷脑瓉?lái)只需要確定函數(shù)名是否在全局命名空間中唯一,變成有必要確定和該函數(shù)關(guān)聯(lián)的數(shù)組的名稱是否在全局命名空間中保持唯一。

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

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

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

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

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

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

      空字符串僅僅被用來(lái)作為一個(gè)占位符,它將被內(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>'
      ];

      /*
      返回一個(gè)內(nèi)部函數(shù)對(duì)象,他是函數(shù)表達(dá)式執(zhí)行返回的結(jié)果
      */
      return (function (url, id, width, height, top, left, altText) {
        /*
        分配各種參數(shù)給對(duì)應(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;

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

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

感謝各位的閱讀!關(guān)于“JS閉包可被利用的常見(jiàn)場(chǎng)景有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

分享題目:JS閉包可被利用的常見(jiàn)場(chǎng)景有哪些
鏈接分享:http://jinyejixie.com/article36/ghhgpg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、搜索引擎優(yōu)化、網(wǎng)站收錄、網(wǎng)站營(yíng)銷、響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作
余姚市| 乌海市| 湖南省| 岫岩| 广饶县| 东源县| 梁平县| 察雅县| 宕昌县| 灌阳县| 嘉荫县| 西贡区| 昭通市| 彰武县| 东乡族自治县| 大邑县| 浮梁县| 墨竹工卡县| 山阳县| 全椒县| 筠连县| 新民市| 沐川县| 饶阳县| 乌海市| 龙游县| 朝阳市| 辽阳市| 巢湖市| 苍山县| 三明市| 介休市| 博客| 新宾| 鲁甸县| 临武县| 象山县| 秦皇岛市| 曲周县| 龙胜| 阳新县|