理解javascript中的回调函数(callback)
最近在看express,满眼看去,到处是以函数作为参数的回调函数的使用。如果这个概念理解不了,nodejs、express的代码就会看得一塌糊涂。比如:
app.use(function(req,res,next){ varerr=newError('NotFound'); err.status=404; next(err); });
app是对象,use是方法,方法的参数是一个带参的匿名函数,函数体直接在后面给出了。这段代码怎么理解呢?我们先来了解回调函数这个概念。
首先要了解,在js中,函数也是对象,可以赋值给变量,可以作为参数放在函数的参数列表中。比如:
vardoSomething=function(a,b) { returna+b; }
这段代码的意思是定义一个匿名函数,这个匿名函数除了没有名字之外,其他跟普通的函数没有什么两样。然后把匿名函数赋值给变量doSomething。接下来我们调用:
console.log(doSomething(2,3));
这样会输出5。
回调函数,就是放在另外一个函数(如parent)的参数列表中,作为参数传递给这个parent,然后在parent函数体的某个位置执行。说来抽象,看例子:
//Toillustratetheconceptofcallback vardoit=function(callback) { vara=1, b=2, c=3; vart=callback(a,b,c); returnt+10; }; vard=doit(function(x,y,z){ return(x+y+z); }); console.log(d);
先定义doit函数,有一个参数callback。这个callback就是回调函数,名字可以任意取。看函数体,先定义三个变量a,b,c。然后调用callback函数。最后返回一个值。
下面就调用doit函数了。要注意的是,刚才定义doit时,callback并没有定义,所以刚才并不知道callback是干什么用的。这其实很好理解,我们平时定义函数的时候,参数也只是给出了一个名字,比如a,在函数体中使用a,但整个过程也并不知道a到底是什么,只有在调用那个函数的时候才指定a的具体值,比如2.回过头来,在调用doit的时候,我们就需要指定callback究竟是个什么东西了。可以看到,这个函数完成了一个sum功能。
上述代码的执行过程是:
调用doit函数,参数是一个匿名函数;进入doit的函数体中,先定义a,b,c,然后执行刚才的匿名函数,参数是a,b,c,并返回一个t,最后返回一个t+10给d。
回到最初的例子,app.use(...)是函数调用。我们可以想象,之前一定定义了一个use方法,只是这里没有给出。这两个例子一对比,就可以马上理解了。
在使用nodejs、express的时候,不可能每个方法或函数我们都要找到它的函数定义去看一看。所以只要知道那个定义里面给callback传递了什么参数就行了。然后在调用方法或函数时,在参数里我们自己定义匿名函数来完成某些功能。
Over!