To prawie to samo co:
if (typeof callback === 'function') {
callback();
}
Zrobiłem to po to, żeby nasza funkcja osłonowa myFadeOut też mogła przyjmować ten opcjonalny parametr callback. Pierwsza z tych trzech powyższych linijek sprawdza, czy go podano i czy jest to funkcja (gdyby parametru nie podano, to typeof callback zwróciłoby 'undefined'). Tylko że to typeof nie zawsze działa (długa historia), więc użyłem funkcji jQuery.isFunction(v). Ona po prostu sprawdza, czy v jest funkcją. Jeśli jest, to zwraca true -- w przeciwnym wypadku zwraca false. Efekt ten sam, tylko kod bardziej "przenośny".
Druga linijka, callback(), to po prostu wywołanie funkcji przekazanej w parametrze callback.
Czyli całość działa tak, że jeśli naszej funkcji myFadeIn podano w drugim parametrze funkcję do odpalenia po zakończeniu animacji, to w tym momencie ją odpalamy.
A czemu napisałem callback.call(this) zamiast po prostu callback()? Cóż, funkcja składowa call to element języka JavaScript. Funkcja ta jest dostępna w każdej zmiennej, która... jest funkcją.
Działa to tak, że gdy napiszesz:
fff.call(kontekst)
...to wewnątrz funkcji fff this będzie wskazywało na obiekt kontekst. A zgodnie ze specyfikacją jQuery, w funkcji callback this powinno wskazywać na bieżący element (element drzewa DOM). To trochę śmieszna sprawa, bo w grę wchodzi tu błąd języka JavaScript... Gubiony jest kontekst, czyli właśnie wartość this. W naszej funkcji anonimowej, w której mamy linijki "this.style.display = ...." this jest ustawiony na bieżący element DOM. Zapewnia nam to jQuery. Na końcu funkcji chcemy wywołać funkcję callback. Ale jakbyśmy wywołali ją tak:
this.style.display = ''; // tu this wskazuje na element DOM!
callback();
To wewnątrz funkcji callback this nie wskazywałoby już na element DOM, tylko... obiekt globalny window. To jest właśnie ten błąd języka JavaScript. Jeden z bardziej irytujących. Kontekst nie jest zachowany. A my chcemy, by wewnątrz callback this wskazywało na to samo, na co wskazuje this w funkcji zewnętrznej (tej z this.style.display itd.). Więc robimy:
callback.call(this);
To wywołuje funkcję callback tak samo jakbyś napisał po prostu callback(); z tą jednak różnicą, że w funkcji callback this będzie ustawione na to, na co jest ustawione this w funkcji zewnętrznej.
To jest zawiłe do tłumaczenia i trudne do zrozumienia (bo jest głupie!), ale gdy to zjarzysz to wydaje Ci się to już bardzo proste.
edit: To może powiem po co jeszcze w ogóle to robimy :D
Funkcja fadeOut ma drugi parametr, który zwą sobie callback i który jest funkcją wywoływaną po zakończeniu animacji. Parametr ten jest opcjonalny. My chcemy, by nasza własna funkcja myFadeOut też miała taki opcjonalny parametr. Na wypadek, gdyby ktoś chciał go użyć. Więc go papugujemy. Dzięki temu można będzie wywołać:
$(...).myFadeOut('slow', function() {
alert('animacja zakończona!');
});
Ale Ty pewnie na razie nie będziesz z tego korzystał, tylko napiszesz tak (możesz, bo parametr jest opcjonalny -- sprawdzamy za pomocą isFunction, czy podano funkcję i próbujemy ją wywołać tylko gdy ją podano!):
$(...).myFadeOut('slow');