C#有lambda、匿名函数,js有匿名函数、闭包,OC中有block,看到这是不是心中有一万个草泥马在跑,不过它们这些都是换汤不换药,不同语言名字不一样。
从功能性上说lambda和closure(或是OC中的blocks)是一个东西,只是不同语言的不同称呼罢了,它们都是匿名函数。若匿名函数捕获了一个外部变量,那么它就是一个closure。
为什么会有这个东东呢?
使用它们一般会有两个好处:简洁、捕获变量.
1.简洁
比如一个方法只在这一处使用,我们就没有必要创建方法然后调用,我们可以直接在其他函数内部声明定义,这样将来查找也不用去其他地方查找了也是比较方便的。例如OC中页面传值一般用代理或block,代理的话每次都要设置delagate,实现代理方法,创建的对象和代理方法分离,这样以后维护某个功能,就可能会忘记实现代理。
2.捕获变量
捕获变量在js中更能说明了。由于js中的作用域和其他语言的不一样.闭包其实就是函数的嵌套,内层的函数可以使用外层函数的所有变量,即使外层函数已经执行完毕。使用闭包减少对全局变量是使用.
这里顺便学一下node.js在回调中实现闭包。
function logCar(logMsg, callback){
process.nextTick(function() {
callback(logMsg);
});
}
var cars = ["Ferrari", "Porsche", "Bugatti"];
for (var idx in cars){
var message = "Saw a " + cars[idx];
logCar(message, function(){
console.log("Normal Callback: " + message);
});
}
for (var idx in cars){
var message = "Saw a " + cars[idx];
(function(msg){
logCar(msg, function(){
console.log("Closure Callback: " + msg);
});
})(message);
}
"C:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe" F:\nodejs\node.exe callback_closure.js
Normal Callback: Saw a Bugatti
Normal Callback: Saw a Bugatti
Normal Callback: Saw a Bugatti
Closure Callback: Saw a Ferrari
Closure Callback: Saw a Porsche
Closure Callback: Saw a Bugatti
Process finished with exit code 0
从上面的代码的输出结果我们来分析:
1.process.nectTick()是异步,在for循环之后执行的回调。
2.在第一个for循环中message对于logCar来说是一个全局变量,每次循环都会改变message,这样最终执行回调是message是最后的值
3.在第二个for循环中使用闭包嵌套了一个函数,每次传个匿名函数的值是message的一个拷贝,每次回调输出时并不是全局变量message,所以会正确输出。