成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

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

mj / 503人閱讀

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

JavaScript與回調(diào)函數(shù)
    var emitter = {
        // 為了能夠注冊(cè)多個(gè)回調(diào)函數(shù)而通過(guò)數(shù)組管理
        callbacks:[],
        // 回調(diào)函數(shù)的注冊(cè)方法
        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"

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

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

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

    function MyClass(msg) {
        this.msg = msg;
        this.show = function () {alert(this.msg+" is called");}
    }
    // 將方法注冊(cè)為回調(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ù)無(wú)法正確顯示this.msg,錯(cuò)誤原因在于JavaScript內(nèi)的this引用。解決方法有兩種,一種是使用bind,一種是不使用方法而是用對(duì)象進(jìn)行注冊(cè)。后者在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對(duì)象的方法。bind的作用和apply與call相同,都是用于明確指定出方法調(diào)用時(shí)的this引用。對(duì)于函數(shù)來(lái)說(shuō),調(diào)用了bind之后會(huì)返回一個(gè)新函數(shù),新的函數(shù)會(huì)執(zhí)行與原函數(shù)相同的內(nèi)容,不過(guò)其this引用是被指定為它的第一個(gè)參數(shù)的對(duì)象。在調(diào)用apply與call時(shí)將會(huì)立即調(diào)用目標(biāo)函數(shù),而在調(diào)用bind時(shí)則不會(huì)如此,而是會(huì)返回一個(gè)函數(shù)(閉包)。
如果使用了apply或call,就能對(duì)bind進(jìn)行獨(dú)立的實(shí)現(xiàn)。事實(shí)上在ES5才推出之前,在prototype.js等知名的庫(kù)中就通過(guò)apply/call提供了bind自己的實(shí)現(xiàn)。

腦補(bǔ)的bind的內(nèi)部實(shí)現(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    對(duì)啦?。?!"};
    
    var testfn = obj.fn.bind(obj2);
    testfn();    // "obj2.x    對(duì)啦?。?!"

閉包與回調(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ù)的說(shuō)明仿佛不在存在,可以很輕松的實(shí)現(xiàn)回調(diào)函數(shù),并且還能像對(duì)象一樣具有狀態(tài)。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83473.html

相關(guān)文章

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

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

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

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

    monw3c 評(píng)論0 收藏0
  • html-webpack-plugin用法全解

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

    JinB 評(píng)論0 收藏0
  • 前端20個(gè)真正靈魂拷問(wèn),吃透這些你就是中級(jí)前端工程師 【上篇】

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

    mdluo 評(píng)論0 收藏0
  • 前端20個(gè)真正靈魂拷問(wèn),吃透這些你就是中級(jí)前端工程師 【上篇】

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

    leap_frog 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

mj

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<