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,所以會正確輸出。