Heim  >  Artikel  >  Web-Frontend  >  关于回调函数,匿名函数,闭包的杂谈

关于回调函数,匿名函数,闭包的杂谈

高洛峰
高洛峰Original
2016-11-21 14:11:111065Durchsuche

回调函数

回调函数,对于初入编程这一行的同学可能会有些难以理解,毕竟回调函数的使用和程序顺序执行的直观流程是相悖的。

想象你定了一个外卖,一种是你定时去查看外卖有没有到,一种是你出示电话号码给外卖员,到达的时候电话通知你。

很容易可以看出第二种是更加高效的方案,其实这种通知机制应用到编程领域,就是回调函数了。

熟悉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变量,语法上便捷了许多。


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn