Mam kilka funkcji, które od czasu do czasu (nie zawsze) odbierają wywołanie zwrotne i je uruchamiają. Czy sprawdzenie, czy callback jest zdefiniowana / funkcja jest dobrym stylem, czy jest lepszy sposób?
Przykład:
function save (callback){
.....do stuff......
if(typeof callback !== 'undefined'){
callback();
};
};
javascript
coding-style
callback
henry.oswald
źródło
źródło
typeof callback !== undefined
więc pomiń'
save()
? Czy to nie spowoduje błędu lub ostrzeżenia o lintingu z powodu braku argumentu? Czy jest w porządku, a oddzwonienie jest po prostuundefined
?Odpowiedzi:
Osobiście wolę
typeof callback === 'function' && callback();
typeof
Polecenia jest jednak ryzykowna i powinny być wykorzystywane tylko dla"undefined"
i"function"
Problem z tym
typeof !== undefined
polega na tym, że użytkownik może przekazać zdefiniowaną wartość, a nie funkcjęźródło
typeof
nie jest podejrzana. Czasami jest niejasny, ale nie nazwałbym tego podejrzanym. Uzgodniono jednak, że jeśli zamierzasz wywołać funkcję zwrotną jako funkcję, najlepiej sprawdzić, czy jest to faktycznie funkcja, a nie, wiesz, numer. :-)"object"
95% przypadków.typeof
nie powoduje boksu.typeof "foo"
jest"string"
, nie"object"
. Właściwie to jedyny prawdziwy sposób, w jaki możesz stwierdzić, czy masz do czynienia z prymitywem łańcuchowym, czyString
obiektem. (Być może myślisz o tymObject.prototype.toString
, co jest bardzo przydatne , ale powoduje boks).&&
przy okazji..toString
jest cudownie znaleźć[[Class]]
.Możesz też:
var noop = function(){}; // do nothing. function save (callback){ callback = callback || noop; .....do stuff...... };
Jest to szczególnie przydatne, jeśli zdarzy ci się używać
callback
w kilku miejscach.Dodatkowo, jeśli używasz
jQuery
, masz już taką funkcję, nazywa się $ .noopźródło
callback = callback || function(){};
function save (callback=noop) { ...
Po prostu zrób
if (callback) callback();
Wolę wywołać oddzwonienie, jeśli jest dostępne, bez względu na jego typ. Nie pozwól mu zawieść po cichu, aby osoba wdrażająca wie, że przekazał niepoprawny argument i może to naprawić.
źródło
ECMAScript 6
// @param callback Default value is a noop fn. function save(callback = ()=>{}) { // do stuff... callback(); }
źródło
Zamiast ustawiać funkcję zwrotną jako opcjonalną, po prostu przypisz wartość domyślną i wywołaj ją bez względu na wszystko
const identity = x => x const save (..., callback = identity) { // ... return callback (...) }
Kiedy jest używany
save (...) // callback has no effect save (..., console.log) // console.log is used as callback
Taki styl nazywa się stylem przechodzenia kontynuacji . Oto prawdziwy przykład,
combinations
który generuje wszystkie możliwe kombinacje danych wejściowych Arrayconst identity = x => x const None = Symbol () const combinations = ([ x = None, ...rest ], callback = identity) => x === None ? callback ([[]]) : combinations ( rest , combs => callback (combs .concat (combs .map (c => [ x, ...c ]))) ) console.log (combinations (['A', 'B', 'C'])) // [ [] // , [ 'C' ] // , [ 'B' ] // , [ 'B', 'C' ] // , [ 'A' ] // , [ 'A', 'C' ] // , [ 'A', 'B' ] // , [ 'A', 'B', 'C' ] // ]
Ponieważ
combinations
jest zdefiniowane w stylu przekazywania kontynuacji, powyższe wywołanie jest w rzeczywistości takie samocombinations (['A', 'B', 'C'], console.log) // [ [] // , [ 'C' ] // , [ 'B' ] // , [ 'B', 'C' ] // , [ 'A' ] // , [ 'A', 'C' ] // , [ 'A', 'B' ] // , [ 'A', 'B', 'C' ] // ]
Możemy również przekazać niestandardową kontynuację, która robi coś innego z wynikiem
console.log (combinations (['A', 'B', 'C'], combs => combs.length)) // 8 // (8 total combinations)
Styl przekazywania kontynuacji może być stosowany z zaskakująco eleganckimi wynikami
const first = (x, y) => x const fibonacci = (n, callback = first) => n === 0 ? callback (0, 1) : fibonacci ( n - 1 , (a, b) => callback (b, a + b) ) console.log (fibonacci (10)) // 55 // 55 is the 10th fibonacci number // (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...)
źródło
Byłem tak zmęczony ciągłym oglądaniem tego samego fragmentu, który napisałem:
var cb = function(g) { if (g) { var args = Array.prototype.slice.call(arguments); args.shift(); g.apply(null, args); } };
Mam setki funkcji wykonujących takie rzeczy jak
cb(callback, { error : null }, [0, 3, 5], true);
lub cokolwiek...
Jestem sceptyczny co do całej strategii „upewnij się, że to funkcja”. Jedyne słuszne wartości to funkcja lub fałsz. Jeśli ktoś poda niezerową liczbę lub niepusty łańcuch, co zamierzasz zrobić? W jaki sposób ignorowanie problemu rozwiązuje go?
źródło
save( { callback : confirmProfileSaved, priority: "low" })
Prawidłowa funkcja jest oparta na prototypie funkcji, użyj:
if (callback instanceof Function)
aby upewnić się, że wywołanie zwrotne jest funkcją
źródło
Jeśli kryterium uruchomienia wywołania zwrotnego jest takie, czy jest zdefiniowane, czy nie, wszystko jest w porządku. Proponuję też sprawdzić, czy to naprawdę funkcja dodatkowa.
źródło
Zgrzeszyłem i przeszedłem do coffee-script i stwierdziłem, że domyślne argumenty to dobry sposób na rozwiązanie tego problemu
źródło
Można to łatwo zrobić za pomocą ArgueJS :
function save (){ arguments = __({callback: [Function]}) .....do stuff...... if(arguments.callback){ callback(); }; };
źródło