欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

JavaScript中回調(diào)函數(shù)的使用方法

這篇文章主要介紹了JavaScript中回調(diào)函數(shù)的使用方法,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)建站服務(wù)項目包括鄂倫春網(wǎng)站建設(shè)、鄂倫春網(wǎng)站制作、鄂倫春網(wǎng)頁制作以及鄂倫春網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,鄂倫春網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到鄂倫春省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

在JavaScript中,函數(shù)是第一類對象,這意味著函數(shù)可以像對象一樣按照第一類管理被使用。既然函數(shù)實際上是對象:它們能被“存儲”在變量中,能作為函數(shù)參數(shù)被傳遞,能在函數(shù)中被創(chuàng)建,能從函數(shù)中返回。

因為函數(shù)是第一類對象,我們可以在JavaScript使用回調(diào)函數(shù)。在下面的文章中,我們將學到關(guān)于回調(diào)函數(shù)的方方面面?;卣{(diào)函數(shù)可能是在JavaScript中使用最多的函數(shù)式編程技巧,雖然在字面上看起來它們一直一小段JavaScript或者jQuery代碼,但是對于許多開發(fā)者來說它任然是一個謎。在閱讀本文之后你能了解怎樣使用回調(diào)函數(shù)。

回調(diào)函數(shù)是從一個叫函數(shù)式編程的編程范式中衍生出來的概念。簡單來說,函數(shù)式編程就是使用函數(shù)作為變量。函數(shù)式編程過去 - 甚至是現(xiàn)在,依舊沒有被廣泛使用 - 它過去常被看做是那些受過特許訓(xùn)練的,大師級別的程序員的秘傳技巧。

幸運的是,函數(shù)是編程的技巧現(xiàn)在已經(jīng)被充分闡明因此像我和你這樣的普通人也能去輕松使用它。函數(shù)式編程中的一個主要技巧就是回調(diào)函數(shù)。在后面內(nèi)容中你會發(fā)現(xiàn)實現(xiàn)回調(diào)函數(shù)其實就和普通函數(shù)傳參一樣簡單。這個技巧是如此的簡單以致于我常常感到很奇怪為什么它經(jīng)常被包含在講述JavaScript高級技巧的章節(jié)中。

什么是回調(diào)或者高階函數(shù)

一個回調(diào)函數(shù),也被稱為高階函數(shù),是一個被作為參數(shù)傳遞給另一個函數(shù)(在這里我們把另一個函數(shù)叫做otherFunction)的函數(shù),回調(diào)函數(shù)在otherFunction中被調(diào)用。一個回調(diào)函數(shù)本質(zhì)上是一種編程模式(為一個常見問題創(chuàng)建的解決方案),因此,使用回調(diào)函數(shù)也叫做回調(diào)模式。

下面是一個在jQuery中使用回調(diào)函數(shù)簡單普遍的例子:

//注意到click方法中是一個函數(shù)而不是一個變量
//它就是回調(diào)函數(shù)
$("#btn_1").click(function() {
    alert("Btn 1 Clicked");
});

正如你在前面的例子中看到的,我們將一個函數(shù)作為參數(shù)傳遞給了click方法。click方法會調(diào)用(或者執(zhí)行)我們傳遞給它的函數(shù)。這是JavaScript中回調(diào)函數(shù)的典型用法,它在jQuery中廣泛被使用。

下面是另一個JavaScript中典型的回調(diào)函數(shù)的例子:

var friends = ["Mike", "Stacy", "Andy", "Rick"];

friends.forEach(function (eachName, index){
    console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick
});

再一次,注意到我們講一個匿名函數(shù)(沒有名字的函數(shù))作為參數(shù)傳遞給了forEach方法。

到目前為止,我們將匿名函數(shù)作為參數(shù)傳遞給了另一個函數(shù)或方法。在我們看更多的實際例子和編寫我們自己的回調(diào)函數(shù)之前,先來理解回調(diào)函數(shù)是怎樣運作的。

回調(diào)函數(shù)是怎樣運作的?

因為函數(shù)在JavaScript中是第一類對象,我們像對待對象一樣對待函數(shù),因此我們能像傳遞變量一樣傳遞函數(shù),在函數(shù)中返回函數(shù),在其他函數(shù)中使用函數(shù)。當我們將一個回調(diào)函數(shù)作為參數(shù)傳遞給另一個函數(shù)是,我們僅僅傳遞了函數(shù)定義。我們并沒有在參數(shù)中執(zhí)行函數(shù)。我們并不傳遞像我們平時執(zhí)行函數(shù)一樣帶有一對執(zhí)行小括號()的函數(shù)。

需要注意的很重要的一點是回調(diào)函數(shù)并不會馬上被執(zhí)行。它會在包含它的函數(shù)內(nèi)的某個特定時間點被“回調(diào)”(就像它的名字一樣)。因此,即使第一個jQuery的例子如下所示:

//匿名函數(shù)不會再參數(shù)中被執(zhí)行
//這是一個回調(diào)函數(shù)
$("#btn_1").click(function(){
    alert("Btn 1 Clicked");
});

這個匿名函數(shù)稍后會在函數(shù)體內(nèi)被調(diào)用。即使有名字,它依然在包含它的函數(shù)內(nèi)通過arguments對象獲取。

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

都能夠?qū)⒁粋€回調(diào)函數(shù)作為變量傳遞給另一個函數(shù)時,這個回調(diào)函數(shù)在包含它的函數(shù)內(nèi)的某一點執(zhí)行,就好像這個回調(diào)函數(shù)是在包含它的函數(shù)中定義的一樣。這意味著回調(diào)函數(shù)本質(zhì)上是一個閉包。

正如我們所知,閉包能夠進入包含它的函數(shù)的作用域,因此回調(diào)函數(shù)能獲取包含它的函數(shù)中的變量,以及全局作用域中的變量。

實現(xiàn)回調(diào)函數(shù)的基本原理

回調(diào)函數(shù)并不復(fù)雜,但是在我們開始創(chuàng)建并使用回調(diào)函數(shù)之前,我們應(yīng)該熟悉幾個實現(xiàn)回調(diào)函數(shù)的基本原理。

使用命名或匿名函數(shù)作為回調(diào)

在前面的jQuery例子以及forEach的例子中,我們使用了在參數(shù)位置定義的匿名函數(shù)作為回調(diào)函數(shù)。這是在回調(diào)函數(shù)使用中的一種普遍的魔術(shù)。另一種常見的模式是定義一個命名函數(shù)并將函數(shù)名作為變量傳遞給函數(shù)。比如下面的例子:

//全局變量
var allUserData = [];

//普通的logStuff函數(shù),將內(nèi)容打印到控制臺
function logStuff (userData){
    if ( typeof userData === "string"){
        console.log(userData);
    } else if ( typeof userData === "object"){
        for(var item in userData){
            console.log(item + ": " + userData[item]);
        }
    }
}

//一個接收兩個參數(shù)的函數(shù),后面一個是回調(diào)函數(shù)
function getInput (options, callback){
    allUserData.push(options);
    callback(options);
}

//當我們調(diào)用getInput函數(shù)時,我們將logStuff作為一個參數(shù)傳遞給它
//因此logStuff將會在getInput函數(shù)內(nèi)被回調(diào)(或者執(zhí)行)
getInput({name:"Rich",speciality:"Javascript"}, logStuff);
//name:Rich
//speciality:Javascript

傳遞參數(shù)給回調(diào)函數(shù)

既然回調(diào)函數(shù)在執(zhí)行時僅僅是一個普通函數(shù),我們就能給它傳遞參數(shù)。我們能夠傳遞任何包含它的函數(shù)的屬性(或者全局屬性)作為回調(diào)函數(shù)的參數(shù)。在前面的例子中,我們將options作為一個參數(shù)傳遞給了回調(diào)函數(shù)?,F(xiàn)在我們傳遞一個全局變量和一個本地變量:

//全局變量
var generalLastName = "Cliton";

function getInput (options, callback){
    allUserData.push (options);
    //將全局變量generalLastName傳遞給回調(diào)函數(shù)
    callback(generalLastName,options);
}

在執(zhí)行之前確?;卣{(diào)函數(shù)是一個函數(shù)

在調(diào)用之前檢查作為參數(shù)被傳遞的回調(diào)函數(shù)確實是一個函數(shù),這樣的做法是明智的。同時,這也是一個實現(xiàn)條件回調(diào)函數(shù)的最佳時間。

我們來重構(gòu)上面例子中的getInput函數(shù)來確保檢查是恰當?shù)摹?/p>

function getInput(options, callback){
    allUserData.push(options);
    
    //確保callback是一個函數(shù)
    if(typeof callback === "function"){
        //調(diào)用它,既然我們已經(jīng)確定了它是可調(diào)用的
        callback(options);
    }
}

如果沒有適當?shù)臋z查,如果getInput的參數(shù)中沒有一個回調(diào)函數(shù)或者傳遞的回調(diào)函數(shù)事實上并不是一個函數(shù),我們的代碼將會導(dǎo)致運行錯誤。

使用this對象的方法作為回調(diào)函數(shù)時的問題

當回調(diào)函數(shù)是一個this對象的方法時,我們必須改變執(zhí)行回調(diào)函數(shù)的方法來保證this對象的上下文。否則如果回調(diào)函數(shù)被傳遞給一個全局函數(shù),this對象要么指向全局window對象(在瀏覽器中)。要么指向包含方法的對象。

我們在下面的代碼中說明:

//定義一個擁有一些屬性和一個方法的對象 //我們接著將會把方法作為回調(diào)函數(shù)傳遞給另一個函數(shù)

var clientData = {
    id: 094545,
    fullName "Not Set",
    //setUsrName是一個在clientData對象中的方法
    setUserName: fucntion (firstName, lastName){
        //這指向了對象中的fullName屬性
        this.fullName = firstName + " " + lastName;
    }
} 

function getUserInput(firstName, lastName, callback){
    //在這做些什么來確認firstName/lastName
    //現(xiàn)在存儲names
    callback(firstName, lastName);
}

在下面你的代碼例子中,當clientData.setUsername被執(zhí)行時,this.fullName并沒有設(shè)置clientData對象中的fullName屬性。相反,它將設(shè)置window對象中的fullName屬性,因為getUserInput是一個全局函數(shù)。這是因為全局函數(shù)中的this對象指向window對象。

getUserInput("Barack","Obama",clientData.setUserName);
console.log(clientData,fullName);  //Not Set
//fullName屬性將在window對象中被初始化     
console.log(window.fullName);  //Barack Obama

使用Call和Apply函數(shù)來保存this

我們可以使用Call或者Apply函數(shù)來修復(fù)上面你的問題。到目前為止,我們知道了每個JavaScript中的函數(shù)都有兩個方法:CallApply。這些方法被用來設(shè)置函數(shù)內(nèi)部的this對象以及給此函數(shù)傳遞變量。

call接收的第一個參數(shù)為被用來在函數(shù)內(nèi)部當做this的對象,傳遞給函數(shù)的參數(shù)被挨個傳遞(當然使用逗號分開)。Apply函數(shù)的第一個參數(shù)也是在函數(shù)內(nèi)部作為this的對象,然而最后一個參數(shù)確是傳遞給函數(shù)的值的數(shù)組。

聽起來很復(fù)雜,那么我們來看看使用ApplyCall有多么的簡單。為了修復(fù)前面例子的問題,我將在下面你的例子中使用Apply函數(shù):

//注意到我們增加了新的參數(shù)作為回調(diào)對象,叫做“callbackObj”
function getUserInput(firstName, lastName, callback. callbackObj){
    //在這里做些什么來確認名字
    callback.apply(callbackObj, [firstName, lastName]);
}

使用Apply函數(shù)正確設(shè)置了this對象,我們現(xiàn)在正確的執(zhí)行了callback并在clientData對象中正確設(shè)置了fullName屬性:

//我們將clientData.setUserName方法和clientData對象作為參數(shù),clientData對象會被Apply方法使用來設(shè)置this對象     
getUserName("Barack", "Obama", clientData.setUserName, clientData);

//clientData中的fullName屬性被正確的設(shè)置
console.log(clientUser.fullName); //Barack Obama

我們也可以使用Call函數(shù),但是在這個例子中我們使用Apply函數(shù)。

允許多重回調(diào)函數(shù)

我們可以將不止一個的回調(diào)函數(shù)作為參數(shù)傳遞給一個函數(shù),就像我們能夠傳遞不止一個變量一樣。這里有一個關(guān)于jQuery中AJAX的例子:

function successCallback(){
    //在發(fā)送之前做點什么
}
  
function successCallback(){
//在信息被成功接收之后做點什么
}

function completeCallback(){
//在完成之后做點什么
}

function errorCallback(){
    //當錯誤發(fā)生時做點什么
}

$.ajax({
    url:"http://fiddle.jshell.net/favicon.png",
    success:successCallback,
    complete:completeCallback,
    error:errorCallback
});

“回調(diào)地獄”問題以及解決方案

在執(zhí)行異步代碼時,無論以什么順序簡單的執(zhí)行代碼,經(jīng)常情況會變成許多層級的回調(diào)函數(shù)堆積以致代碼變成下面的情形。這些雜亂無章的代碼叫做回調(diào)地獄因為回調(diào)太多而使看懂代碼變得非常困難。我從node-MongoDB-native,一個適用于Node.js的MongoDB驅(qū)動中拿來了一個例子。這段位于下方的代碼將會充分說明回調(diào)地獄:

var p_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), 
                 {'pk':CustomPKFactory});
p_client.open(function(err, p_client) {
    p_client.dropDatabase(function(err, done) {
        p_client.createCollection('test_custom_key', function(err, collection) {
            collection.insert({'a':1}, function(err, docs) {
                collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}, 
                function(err, cursor) {
                    cursor.toArray(function(err, items) {
                        test.assertEquals(1, items.length);
                        // Let's close the db
                        p_client.close();
                    });
                });
            });
        });
    });
});

你應(yīng)該不想在你的代碼中遇到這樣的問題,當你當你遇到了

  • 你將會時不時的遇到這種情況

  • 這里有關(guān)于這個問題的兩種解決方案。

  • 給你的函數(shù)命名并傳遞它們的名字作為回調(diào)函數(shù),而不是主函數(shù)的參數(shù)中定義匿名函數(shù)。

  • 模塊化L將你的代碼分隔到模塊中,這樣你就可以到處一塊代碼來完成特定的工作。然后你可以在你的巨型應(yīng)用中導(dǎo)入模塊。

創(chuàng)建你自己的回調(diào)函數(shù)

既然你已經(jīng)完全理解了關(guān)于JavaScript中回調(diào)函數(shù)的一切(我認為你已經(jīng)理解了,如果沒有那么快速的重讀以便),你看到了使用回調(diào)函數(shù)是如此的簡單而強大,你應(yīng)該查看你的代碼看看有沒有能使用回調(diào)函數(shù)的地方。回調(diào)函數(shù)將在以下幾個方面幫助你:

  • 避免重復(fù)代碼(DRY-不要重復(fù)你自己)

  • 在你擁有更多多功能函數(shù)的地方實現(xiàn)更好的抽象(依然能保持所有功能)

  • 讓代碼具有更好的可維護性

  • 使代碼更容易閱讀

  • 編寫更多特定功能的函數(shù)

創(chuàng)建你的回調(diào)函數(shù)非常簡單。在下面的例子中,我將創(chuàng)建一個函數(shù)完成以下工作:讀取用戶信息,用數(shù)據(jù)創(chuàng)建一首通用的詩,并且歡迎用戶。這本來是個非常復(fù)雜的函數(shù)因為它包含很多if/else語句并且,它將在調(diào)用那些用戶數(shù)據(jù)需要的功能方面有諸多限制和不兼容性。

相反,我用回調(diào)函數(shù)實現(xiàn)了添加功能,這樣一來獲取用戶信息的主函數(shù)便可以通過簡單的將用戶全名和性別作為參數(shù)傳遞給回調(diào)函數(shù)并執(zhí)行來完成任何任務(wù)。

簡單來講,getUserInput函數(shù)是多功能的:它能執(zhí)行具有無種功能的回調(diào)函數(shù)。

//首先,創(chuàng)建通用詩的生成函數(shù);它將作為下面的getUserInput函數(shù)的回調(diào)函數(shù)

function genericPoemMaker(name, gender) {
    console.log(name + " is finer than fine wine.");
    console.log("Altruistic and noble for the modern time.");
    console.log("Always admirably adorned with the latest style.");
    console.log("A " + gender + " of unfortunate tragedies who still manages a perpetual smile");
}

//callback,參數(shù)的最后一項,將會是我們在上面定義的genericPoemMaker函數(shù)
function getUserInput(firstName, lastName, gender, callback) {
    var fullName = firstName + " " + lastName;
    // Make sure the callback is a function
    if (typeof callback === "function") {
    // Execute the callback function and pass the parameters to it
    callback(fullName, gender);
    }
}

調(diào)用getUserInput函數(shù)并將genericPoemMaker函數(shù)作為回調(diào)函數(shù):

getUserInput("Michael", "Fassbender", "Man", genericPoemMaker);
// 輸出
/* Michael Fassbender is finer than fine wine.
Altruistic and noble for the modern time.
Always admirably adorned with the latest style.
A Man of unfortunate tragedies who still manages a perpetual smile.
*/

因為getUserInput函數(shù)僅僅只負責提取數(shù)據(jù),我們可以把任意回調(diào)函數(shù)傳遞給它。例如,我們可以傳遞一個greetUser函數(shù):

unction greetUser(customerName, sex)  {
    var salutation  = sex && sex === "Man" ? "Mr." : "Ms.";
    console.log("Hello, " + salutation + " " + customerName);
}

// 將greetUser作為一個回調(diào)函數(shù)
getUserInput("Bill", "Gates", "Man", greetUser);

// 這里是輸出
Hello, Mr. Bill Gates

我們調(diào)用了完全相同的getUserInput函數(shù),但是這次完成了一個完全不同的任務(wù)。

正如你所見,回調(diào)函數(shù)很神奇。即使前面的例子相對簡單,想象一下能節(jié)省多少工作量,你的代碼將會變得更加的抽象,這一切只需要你開始使用毀掉函數(shù)。大膽的去使用吧。

在JavaScript編程中回調(diào)函數(shù)經(jīng)常以幾種方式被使用,尤其是在現(xiàn)代Web應(yīng)用開發(fā)以及庫和框架中:

  • 異步調(diào)用(例如讀取文件,進行HTTP請求,等等)

  • 時間監(jiān)聽器/處理器

  • setTimeoutsetInterval方法

  • 一般情況:精簡代碼

結(jié)束語

JavaScript回調(diào)函數(shù)非常美妙且功能強大,它們?yōu)槟愕腤eb應(yīng)用和代碼提供了諸多好處。你應(yīng)該在有需求時使用它;或者為了代碼的抽象性,可維護性以及可讀性而使用回調(diào)函數(shù)來重構(gòu)你的代碼。

感謝你能夠認真閱讀完這篇文章,希望小編分享JavaScript中回調(diào)函數(shù)的使用方法內(nèi)容對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問題就找創(chuàng)新互聯(lián),詳細的解決方法等著你來學習!

文章題目:JavaScript中回調(diào)函數(shù)的使用方法
轉(zhuǎn)載源于:http://aaarwkj.com/article48/ihpjhp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計、App設(shè)計、網(wǎng)站導(dǎo)航、網(wǎng)站策劃動態(tài)網(wǎng)站、Google

廣告

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

成都定制網(wǎng)站建設(shè)
国产av综合一区二区三区最新| 高清中文字幕一区二区三区| 中文字幕免费日本在线| 欧美高清一区二区三区精品| 亚洲精品成人福利网站| 欧美伊香蕉久久综合网99| 91久久精品91久久性色| 国产区一区二区三在线播放| 日本三级黄色免费的网站| 日韩av在线专区观看| 亚洲一区二区三区日本在线| 未满18十八禁止观看| av中文在线免费观看| 国产精品一区午夜福利| 国产区青青操自拍视频| 最新日韩中文字幕在线播放| 精品国产亚洲av未满十八| 欧美大片免费在线播放| 久久精品国产亚洲夜色av网站| 亚洲av天堂在线观看| 麻豆午夜视频免费在线观看| 欧洲一区二区在线激情| 久草视频免费福利观看| 国产口爆一区二区三区| 国产不卡视频观看网站| 偷窥偷拍视频一区二区| 亚洲一区二区三区精品日韩| 亚洲欧美激情专区在线| 日韩欧美中文字幕区| 国产精品成人大片在线播放| 国产精品一区二区日韩新区| 国产精品盗摄一区二区三区| 亚洲少妇午夜福利视频| 亚洲无综合素人在线观看| 亚洲美女毛茸茸的逼逼| 欧美亚洲精品一区二区三区| 人人妻人人澡人人爽人人老司机| 欧美国产精品中文字幕| 日本美女激情在线观看| 亚洲日本精品国产第一区| 日本高清不卡免费在线观看视频一二三区 |