Załóżmy, że mam dowolną zmienną, która jest zdefiniowana w następujący sposób:
var a = function() {/* Statements */};
Chcę funkcji, która sprawdza, czy typ zmiennej jest podobny do funkcji. tj .:
function foo(v) {if (v is function type?) {/* do something */}};
foo(a);
Jak mogę sprawdzić, czy zmienna a
jest typu Function
w sposób określony powyżej?
javascript
Jesufer Vn
źródło
źródło
Odpowiedzi:
Oczywiście sposób podkreślenia jest bardziej wydajny, ale najlepszy sposób sprawdzenia, kiedy wydajność nie jest problemem, jest napisany na stronie podkreślonej przez @Paul Rosania.
Zainspirowany podkreśleniem, końcowa funkcja isFunction jest następująca:
źródło
isFunctionA
pokazuje różnicę w porównaniu do innych metod.typeof(obj) === 'function'
wydaje się zdecydowanie najszybszy; jednak w Firefoxobj instanceof Function
jest wyraźnym zwycięzcą.źródło
typeof Object
,typeof Date
itypeof String
, co wszyscy zwrot'function'
też.if (v instanceOf Function)
?instanceof
że nie zadziała, jeśli sprawdzasz funkcję pochodzącą z innego dokumentu (może to być element iframe). Wydajność jest różna.asyncfunctionToCheck
,getType.toString.call(functionToCheck)==='[object AsyncFunction]'
gdzietypeof asyncfunctionToCheck === 'function'
Underscore.js używa bardziej złożonego, ale wysoce wydajnego testu:
Zobacz: http://jsperf.com/alternative-isfunction-implementations
EDYCJA: zaktualizowane testy sugerują, że typeof może być szybszy, patrz http://jsperf.com/alternative-isfunction-implementations/4
źródło
typof
?typeof == "function"
) - i wydaje się być znacznie szybsza niż „szybka” wersja Underscore.isFunction()
implementacji. Obecnie używa czegoś bardzo zbliżonego do tego, co sugerował dandean .Istnieje kilka sposobów, dlatego streszczę je wszystkie
typeof
jest to, że jest podatny na cichą awarię, źle, więc jeśli masz literówkę (np. „zakończenie”) - w tym przypadku „if” po prostu zwróci fałsz i nie będziesz wiedział, że masz błąd, dopóki nie Twój kodźródło
top.Function !== Function
. Dla pewności użyj drugiego (mam nadzieję, że wszelkie błędy pisowni „funkcji” zostaną poprawione podczas debugowania).instanceof
, nie bierze pod uwagę wielu globałów, takich jak sprawdzanie w różnych ramkach, i może zwracać fałszywe negatywy.jQuery (przestarzałe od wersji 3.3) Odniesienie
Odniesienie AngularJS
Referencje Lodash
Odniesienie do podkreślenia
Node.js jest przestarzałe od wersji 4.0.0 Reference
źródło
@grandecomplex: W twoim rozwiązaniu jest sporo gadatliwości. Byłoby o wiele jaśniej, gdyby napisano w ten sposób:
źródło
źródło
(() => (typeof obj === 'function') && doSomething())
nadal jest najszybszą opcją.Wypróbuj
instanceof
operator: wygląda na to, że wszystkie funkcje dziedziczą poFunction
klasie:źródło
Coś z większą obsługą przeglądarki i funkcjami asynchronicznymi może być:
a następnie przetestuj:
źródło
Innym prostym sposobem:
źródło
fn && fn.constructor === Function
co powiesz na to?Dla tych, którzy są zainteresowani stylem funkcjonalnym lub szukają bardziej wyrazistego podejścia do wykorzystania w metaprogramowaniu (takim jak sprawdzanie typów), interesujące może być obejrzenie biblioteki Ramda, aby wykonać takie zadanie.
Następny kod zawiera tylko czyste i bezcelowe funkcje:
Począwszy od ES2017,
async
funkcje są dostępne, więc możemy je również sprawdzić:A następnie połącz je razem:
Oczywiście funkcja powinna być chroniona przed wartościami
null
iundefined
wartościami, aby była „bezpieczna”:I uzupełnij fragment kodu, aby podsumować:
Należy jednak pamiętać, że to rozwiązanie może wykazywać mniejszą wydajność niż inne dostępne opcje z powodu szerokiego użycia funkcji wyższego rzędu.
źródło
Jeśli używasz Lodash, możesz to zrobić za pomocą _.isFunkcji .
Ta metoda zwraca,
true
jeśli wartość jest funkcją, w przeciwnym raziefalse
.źródło
Okazało się, że podczas testowania natywne funkcje przeglądarki w IE8, używając
toString
,instanceof
itypeof
nie działa. Oto metoda, która działa dobrze w IE8 (o ile mi wiadomo):Alternatywnie możesz sprawdzić funkcje natywne, używając:
Chociaż gdzieś przeczytałem, że nie zawsze będzie to działać w IE7 i niższych wersjach.
źródło
Poniższe wydaje się również działać dla mnie (testowane z
node.js
):źródło
Myślę, że możesz po prostu zdefiniować flagę na prototypie funkcji i sprawdzić, czy instancja, którą chcesz przetestować, odziedziczyła to
zdefiniuj flagę:
a następnie sprawdź, czy istnieje
Minusem jest to, że inny prototyp może zdefiniować tę samą flagę, a następnie jest bezwartościowy, ale jeśli masz pełną kontrolę nad dołączonymi modułami, jest to najprostszy sposób
źródło
Od węzła v0.11 możesz użyć standardowej funkcji util:
źródło
powinieneś użyć
typeOf
operatora w js.źródło
Rozwiązaniem, jak pokazały niektóre poprzednie odpowiedzi, jest użycie typeof. Oto fragment kodu W NodeJs,
źródło