首頁 > web前端 > js教程 > 關於回呼函數,匿名函數,閉包的雜談

關於回呼函數,匿名函數,閉包的雜談

高洛峰
發布: 2016-11-21 14:11:11
原創
1115 人瀏覽過

回呼函數

回呼函數,對於初入程式設計這一行的同學可能會有些難以理解,畢竟回調函數的使用和程式順序執行的直覺流程是相悖的。

想像你定了一個外賣,一種是你定時去查看外賣有沒有到,一種是你出示電話號碼給外賣員,到達的時候電話通知你。

很容易可以看出第二種是更有效率的方案,其實這種通知機制應用在程式設計領域,就是回呼函數了。

熟悉win32開發的同學應該知道,典型的windows程式框架就是一個訊息循環外加一個視窗過程函數。其中windows系統接管訊息接受,之後呼叫開發者的視窗過程函數來完成具體的訊息處理邏輯。視窗過程函數就是一個回呼函數。

為什麼需要回呼函數

以上面的 win32程式為例。我們知道出於安全性考慮,windows作業系統是不允許開發者直接存取硬體資源的。微軟的開發者提供了api來處理訊息循環,但是具體訊息的回應邏輯需要開發者來提供,這種情況下,回呼函數就是很好的實作方案。

再舉一個例子,想像你參與一個手機設備管理軟體專案的開發工作,你負責底層設備通訊模組。當使用者插入設備到電腦中時,你需要通知上層的模組進行處理。出於靈活性和通用性的考慮,你不可能將裝置連接時的處理邏輯放在你負責的模組中,此時可以由上層呼叫者提供一個回調函數,在裝置連接時你的模組呼叫回調函數即可。

關於回調函數,有一個所謂的好萊塢準則:Don't call me; I'll call you!

匿名函式

在c,c++等語言中,當需要使用回呼函數時,需要預先定義一個函式體。而回調函數通常只是提供給其它模組進行調用,為了簡化編碼,後續的javascript等腳本語言中提供了對匿名函數的支援。 (註: 新的c++標準也開始支援匿名函數,稱為Lambda函數)

getUserInfo:function(cb){
    var that = this
    if(this.globalData.userInfo){
      typeof cb == "function" && cb(this.globalData.userInfo)
    }else{
      //调用登录接口
      wx.login({
        success: function () {
          wx.getUserInfo({
            success: function (res) {
              that.globalData.userInfo = res.userInfo
              typeof cb == "function" && cb(that.globalData.userInfo)
            }
          })
        }
      })
    }
  },
登入後複製

上面的程式碼來自於上一篇教程中的app.js,在調用wx.login時,傳遞了一個匿名函數進行調用成功後的邏輯處理,就是success後面的部分。可以看到這裡只有函數定義而沒有函數名稱,因此除了作為回調函數外,也無法在其它地方呼叫該函數。

其實匿名函數只是一種編碼簡化而已,不過它帶來的好處卻不僅僅是減少編碼而已。

閉包

在程式設計技術中,閉包應該屬於較高階的技術了。當使用回調函數時,通常會涉及一些上下文的傳遞。在c/c++等語言中,會使用全域變數或堆記憶體來傳遞上下文。全域變數的缺點很明顯,而堆記憶體又很容易發生記憶體洩漏。而在更高階的腳本語言中,可以透過閉包技術來輕鬆的完成上下文傳遞。

以上面的程式碼為例,在回調函數中執行了that.globalData.userInfo = res.userInfo來保存使用者訊息,其中that變數由var that = this賦值,因此該變數指向app物件本身,所以才能成功保存用戶資訊。

我們可以看到that物件是getUserInfo方法堆疊上的變量,如果沒有閉包技術,此處的匿名回調函數是不能直接使用that變數的,就需要將app物件傳遞給回調函數(全域變數或函數參數的方式),而在閉包技術的支持下,回調函數可以像使用函數內部變數一樣來存取that變量,語法上便捷了許多。


相關標籤:
js
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板