# 7方法
### 去抖動函數
### 問題
你想只執行某個函數一次,在開始或結束時把多個連續的調用合并成一個簡單的操作。
### 解決方案
使用一個命名函數:
~~~
debounce: (func, threshold, execAsap) ->
timeout = null
(args...) ->
obj = this
delayed = ->
func.apply(obj, args) unless execAsap
timeout = null
if timeout
clearTimeout(timeout)
else if (execAsap)
func.apply(obj, args)
timeout = setTimeout delayed, threshold || 100
mouseMoveHandler: (e) ->
@debounce((e) ->
# 只能在鼠標光標停止 300 毫秒后操作一次。
300)
?
someOtherHandler: (e) ->
@debounce((e) ->
# 只能在初次執行 250 毫秒后操作一次。
250, true)
~~~
### 討論
可參閱 John Hann 的博客文章,了解 [JavaScript 去抖動方法](http://unscriptable.com/2009/03/20/debouncing-javascript-methods/)。
### 當函數括號不可選
### 問題
你想要調用一個沒有參數的函數,但不希望使用括號。
### 解決方案
不管怎樣都使用括號。
另一個方法是使用 do 表示法,如下:
~~~
notify = -> alert "Hello, user!"
do notify if condition
~~~
編譯成 JavaScript 則可表示為:
~~~
var notify;
notify = function() {
return alert("Hello, user!");
};
if (condition) {
notify();
}
~~~
### 討論
這個方法與 Ruby 類似,在于都可以不使用括號來完成方法的調用。而不同點在于,CoffeeScript 把空的函數名作為函數的指針。這樣以來,如果你不賦予一個方法任何參數,那么 CoffeeScript 將無法分辨你是想要調用函數還是把它作為引用。
這是好是壞呢?其實只是有所不同。它創造了一個意想不到的語法實例——括號并不*總是*可選的——但是它能讓你流利地使用名字來傳遞和接收函數,這對于 Ruby 來說是難以實現的。
對于 CoffeeScript 來說,使用 do 表示法是一個巧妙的方法來克服括號使用恐懼癥。盡管有部分人寧愿在函數調用中寫出所有括號。
### 遞歸函數
### 問題
你想在一個函數中調用相同的函數。
### 解決方案
使用一個命名函數:
~~~
ping = ->
console.log "Pinged"
setTimeout ping, 1000
~~~
若為未命名函數,則使用 @arguments.callee@:
~~~
delay = 1000
?
setTimeout((->
console.log "Pinged"
setTimeout arguments.callee, delay
), delay)
~~~
### 討論
雖然 **arguments.callee** 允許未命名函數的遞歸,在內存密集型應用中占有一定優勢,但是命名函數相對來說目的更加明確,也更易于代碼的維護。
### 提示參數
### 問題
你的函數將會被可變數量的參數所調用。
### 解決方案
使用 *splat* 。
~~~
loadTruck = (firstDibs, secondDibs, tooSlow...) ->
truck:
driversSeat: firstDibs
passengerSeat: secondDibs
trunkBed: tooSlow
?
loadTruck("Amanda", "Joel")
# => { truck: { driversSeat: "Amanda", passengerSeat: "Joel", trunkBed: [] } }
?
?
loadTruck("Amanda", "Joel", "Bob", "Mary", "Phillip")
# => { truck: { driversSeat: "Amanda", passengerSeat: "Joel", trunkBed: ["Bob", "Mary", "Phillip"] } }
~~~
使用尾部參數:
~~~
loadTruck = (firstDibs, secondDibs, tooSlow..., leftAtHome) ->
truck:
driversSeat: firstDibs
passengerSeat: secondDibs
trunkBed: tooSlow
taxi:
passengerSeat: leftAtHome
?
loadTruck("Amanda", "Joel", "Bob", "Mary", "Phillip", "Austin")
# => { truck: { driversSeat: 'Amanda', passengerSeat: 'Joel', trunkBed: [ 'Bob', 'Mary', 'Phillip' ] }, taxi: { passengerSeat: 'Austin' } }
?
?
loadTruck("Amanda")
# => { truck: { driversSeat: "Amanda", passengerSeat: undefined, trunkBed: [] }, taxi: undefined }
~~~
### 討論
通過在函數其中的(不多于)一個參數之后添加一個省略號(...),CoffeeScript 能把所有不被其他命名參數采用的參數值整合進一個列表中。就算并沒有提供命名參數,它也會制造一個空列表。