亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

《JS編程全解》—— 回調(diào)函數(shù)

mj / 555人閱讀

摘要:事件驅(qū)動正是一種回調(diào)函數(shù)設(shè)計模式。由于不支持多線程,所以為了實現(xiàn)并行處理,不得不使用回調(diào)函數(shù),這逐漸成為了一種慣例。上面的回調(diào)函數(shù)只是單純的函數(shù)而不具有狀態(tài)。如果回調(diào)函數(shù)具有狀態(tài),就能得到更為廣泛的應(yīng)用。

回調(diào)函數(shù)模式 回調(diào)函數(shù)與控制反轉(zhuǎn)

回調(diào)函數(shù)是程序設(shè)計的一種方法。這種方法是指,在傳遞了可能會進行調(diào)用的函數(shù)或?qū)ο笾?,在需要時再分別對其進行調(diào)用。由于調(diào)用方與被調(diào)用方的依賴關(guān)系與通常相反,所以也成為控制反轉(zhuǎn)(IoC,Inversion of Control)。
由于歷史原因,在JavaScript開發(fā)中我們常常會用到回調(diào)函數(shù)這一方法,這是多種因素導(dǎo)致的。第一個原因是在客戶端JavaScript中基本都是GUI程序設(shè)計。GUI程序設(shè)計是一種很適合使用所謂事件驅(qū)動的程序設(shè)計方式。事件驅(qū)動正是一種回調(diào)函數(shù)設(shè)計模式??蛻舳薐avaScript程序設(shè)計是一種基于DOM的事件驅(qū)動式程序設(shè)計。
第二個原因是,源于客戶端無法實現(xiàn)多線程程序設(shè)計(最近HTML5 Web Works支持多線程了)。而通過將回調(diào)函數(shù)與異步處理相結(jié)合,就能夠?qū)崿F(xiàn)并行處理。由于不支持多線程,所以為了實現(xiàn)并行處理,不得不使用回調(diào)函數(shù),這逐漸成為了一種慣例。最后一個原因與JavaScript中的函數(shù)聲明表達式和閉包有關(guān)。

JavaScript與回調(diào)函數(shù)
    var emitter = {
        // 為了能夠注冊多個回調(diào)函數(shù)而通過數(shù)組管理
        callbacks:[],
        // 回調(diào)函數(shù)的注冊方法
        register:function (fn) {
            this.callbacks.push(fn);
        },
        // 事件的觸發(fā)處理
        onOpen:function () {
            for (var f in this.callbacks) {
                this.callbacks[f]();
            }
        }
    };
    emitter.register(function () {alert("event handler1 is called");})
    emitter.register(function () {alert("event handler2 is called");})
    
    emitter.onOpen();    
    // "event handler1 is called"
    // "event handler2 is called"

定義的兩個匿名函數(shù)就是回調(diào)函數(shù),它們的調(diào)用由emitter.onOpen()完成。

 對emitter來說,這僅僅是對注冊的函數(shù)進行了調(diào)用,不過根據(jù)回調(diào)函數(shù)的定義,更應(yīng)該關(guān)注使用了emitter部分的情況。從這個角度來看,注冊過的回調(diào)函數(shù)與之形成的是一種調(diào)用與被調(diào)用的關(guān)系。

上面的回調(diào)函數(shù)只是單純的函數(shù)而不具有狀態(tài)。如果回調(diào)函數(shù)具有狀態(tài),就能得到更為廣泛的應(yīng)用。下面我們把回調(diào)方改為了對象,于是emitter變?yōu)榱私邮芊椒▊鬟f的形式。

    function MyClass(msg) {
        this.msg = msg;
        this.show = function () {alert(this.msg+" is called");}
    }
    // 將方法注冊為回調(diào)函數(shù)
    var obj = new MyClass("listener1");
    var obj2 = new MyClass("listener2");
    emitter.register(obj.show);
    emitter.register(obj2.show);
    
    emitter.onOpen();
    // undefined is called
    // undefined is called

我們發(fā)現(xiàn),調(diào)用回調(diào)函數(shù)無法正確顯示this.msg,錯誤原因在于JavaScript內(nèi)的this引用。解決方法有兩種,一種是使用bind,一種是不使用方法而是用對象進行注冊。后者在JavaScript中并不常用。

    emitter.register(obj.show.bind(obj));
    emitter.register(obj2.show.bind(obj2));
    
    emitter.onOpen();
    // "listener1 is called"
    // "listener2 is called"

bind是ES5新增的功能,是Function.prototype對象的方法。bind的作用和apply與call相同,都是用于明確指定出方法調(diào)用時的this引用。對于函數(shù)來說,調(diào)用了bind之后會返回一個新函數(shù),新的函數(shù)會執(zhí)行與原函數(shù)相同的內(nèi)容,不過其this引用是被指定為它的第一個參數(shù)的對象。在調(diào)用apply與call時將會立即調(diào)用目標函數(shù),而在調(diào)用bind時則不會如此,而是會返回一個函數(shù)(閉包)。
如果使用了apply或call,就能對bind進行獨立的實現(xiàn)。事實上在ES5才推出之前,在prototype.js等知名的庫中就通過apply/call提供了bind自己的實現(xiàn)。

腦補的bind的內(nèi)部實現(xiàn)?

    Function.prototype.bind = null;
    Function.prototype.bind = function (obj) {
        var f = this;
        return function () {
            f.call(obj);
        }
    }
    var obj = {
        x:"這是    obj.x    ?。?!",
        fn:function () {
            alert(this.x);
        }
    };
    var obj2 = {x:"obj2.x    對啦?。?!"};
    
    var testfn = obj.fn.bind(obj2);
    testfn();    // "obj2.x    對啦?。?!"

閉包與回調(diào)函數(shù)

    emitter.register(
        (function () {
            var msg = "closure1";
            return function () {alert(msg+" is called;")};
        }())
    );
    emitter.register(
        (function () {
            var msg = "closure2";
            return function () {alert(msg+" is called;")};
        }())
    )
    
    emitter.onOpen();
    // "closure1 is called"
    // "closure2 is called"

借助閉包,前面繁復(fù)的說明仿佛不在存在,可以很輕松的實現(xiàn)回調(diào)函數(shù),并且還能像對象一樣具有狀態(tài)。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/83473.html

相關(guān)文章

  • JavaScript編程全解 —— 基礎(chǔ)

    摘要:函數(shù)式編程最后介紹一下函數(shù)式編程。函數(shù)式編程是一種歷史悠久,而又在最近頗為熱門的話題。函數(shù)式編程在面向?qū)ο笠辉~誕生以前就已經(jīng)存在,不過它在很長一段時間里都被隱藏于過程式編程面向?qū)ο笠彩沁^程式編程的一種的概念之下。 2.1 JavaScript特點 總結(jié)以下幾個特點: 解釋型語言 類似與C和Java的語法結(jié)構(gòu) 動態(tài)語言 基于原型的面向?qū)ο?字面量的表現(xiàn)能力 函數(shù)式編程 解釋型語言:...

    CoreDump 評論0 收藏0
  • JavaScript 中優(yōu)雅的實現(xiàn)順序執(zhí)行異步函數(shù)

    摘要:順序執(zhí)行異步函數(shù)異步為帶來非阻塞等優(yōu)勢的同時,同時也在一些場景下帶了不便,如順序執(zhí)行異步函數(shù),下面總結(jié)了一些常用的方法。 火于異步 1995年,當(dāng)時最流行的瀏覽器——網(wǎng)景中開始運行 JavaScript (最初稱為 LiveScript)。 1996年,微軟發(fā)布了 JScript 兼容 JavaScript。隨著網(wǎng)景、微軟競爭而不斷的技術(shù)更新,在 2000年前后,JavaScript ...

    monw3c 評論0 收藏0
  • html-webpack-plugin用法全解

    摘要:所有的這些都是的功勞。默認為根據(jù)自己的指定的模板文件來生成特定的文件。最終在文件夾內(nèi)會生成一個和文件。屬性值為文件所在的路徑名。默認值為不對生成的文件進行壓縮。選項的作用主要是針對多入口文件。不用說,按照不同文件的依賴關(guān)系來排序。 本文只在個人博客和 SegmentFault 社區(qū)個人專欄發(fā)表,轉(zhuǎn)載請注明出處 個人博客: https://zengxiaotao.github.io ...

    JinB 評論0 收藏0
  • 前端20個真正靈魂拷問,吃透這些你就是中級前端工程師 【上篇】

    摘要:還是老規(guī)矩,從易到難吧傳統(tǒng)的定時器,異步編程等。分配對象時,先是在空間中進行分配。內(nèi)存泄漏內(nèi)存泄漏是指程序中己動態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無法釋放,造成系統(tǒng)內(nèi)存的浪費,導(dǎo)致程序運行速度減慢甚至系統(tǒng)崩潰等嚴重后果。 showImg(https://segmentfault.com/img/bVbwkad?w=1286&h=876); 網(wǎng)上參差不棄的面試題,本文由淺入深,讓你在...

    mdluo 評論0 收藏0
  • 前端20個真正靈魂拷問,吃透這些你就是中級前端工程師 【上篇】

    摘要:還是老規(guī)矩,從易到難吧傳統(tǒng)的定時器,異步編程等。分配對象時,先是在空間中進行分配。內(nèi)存泄漏內(nèi)存泄漏是指程序中己動態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無法釋放,造成系統(tǒng)內(nèi)存的浪費,導(dǎo)致程序運行速度減慢甚至系統(tǒng)崩潰等嚴重后果。 showImg(https://segmentfault.com/img/bVbwkad?w=1286&h=876); 網(wǎng)上參差不棄的面試題,本文由淺入深,讓你在...

    leap_frog 評論0 收藏0

發(fā)表評論

0條評論

mj

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<