Jak sprawdzić, czy funkcja istnieje w JavaScript?


533

Mój kod to

function getID( swfID ){
     if(navigator.appName.indexOf("Microsoft") != -1){
          me = window[swfID];
     }else{
          me = document[swfID];
     }
}

function js_to_as( str ){
     me.onChange(str);
}

Czasami jednak mój onChangenie ładuje się. Błędy Firebug z

me.onChange nie jest funkcją

Chcę degradować z wdziękiem, ponieważ nie jest to najważniejsza funkcja w moim programie. typeofdaje ten sam błąd.

Wszelkie sugestie, jak upewnić się, że istnieje, a następnie wykonać tylko onChange?

(Żadna z poniższych metod, z wyjątkiem próby złapania jednej pracy)


1
@ SteveChambers Zrobiłem to. Dziękuję za przypomnienie.
Alec Smart


złap wyjątek. sprawdź moją odpowiedź
Matteus Barbosa

Odpowiedzi:


1224

Wypróbuj coś takiego:

if (typeof me.onChange !== "undefined") { 
    // safe to use the function
}

lub jeszcze lepiej (zgodnie z komentarzem UpTheCreek)

if (typeof me.onChange === "function") { 
    // safe to use the function
}

249
=== „funkcja” byłaby lepsza niż! = „niezdefiniowana”
UpTheCreek

3
@James, ponieważ ta instrukcja faktycznie zgłasza undefinedwyjątek w JavaScript. Próbowałem tego.
Mike Perrenoud,

8
@UpTheCreek, byłoby to trochę niebezpieczne jako ogólne rozwiązanie, ponieważ starsze wersje IE traktują niektóre funkcje jako obiekty, np typeof window.alert === 'object'.
Noyo,

1
Dlaczego nie po prostu użyć if (me.onChange) { // do something }?
BornToCode

3
@BornToCode, ponieważ wtedy me.onChangemoże być czymkolwiek oceniającym true, niekoniecznie funkcją (np. Może to być wartość logiczna, ciąg znaków itp.). Na przykład patrz jsfiddle.net/j5KAF/1
Ohad Schneider

108

Miałem ten problem.

if (obj && typeof obj === 'function') { ... }

ciągle zgłaszał błąd referencyjny, jeśli obj się zdefiniowany.

Na koniec zrobiłem następujące:

if (typeof obj !== 'undefined' && typeof obj === 'function') { ... }

Kolega zwrócił mi uwagę, że sprawdzenie, czy tak jest, !== 'undefined'a następnie === 'function'jest zbędne.

Prostsze:

if (typeof obj === 'function') { ... }

Dużo czystszy i działa świetnie.


1
Czy ktoś ma pojęcie, dlaczego rzuca pierwszy fragment kodu ReferenceError? To wydaje mi się nielogiczne.
powiedział poganie


to działa dla mnie
NewBie1234

1
Jakiś motyw, dla którego typeof obj == „funkcja” byłaby niewystarczająca? ;-) Przypomnienie: operator ścisłego testu równości ma sens tylko wtedy, gdy statyczny operand jest pusty, zerowy lub zerowy lub podlega takiej rzutowanej kombinacji.
Fabien Haddadi

16

Jeśli używasz eval do konwersji ciągu na funkcję i chcesz sprawdzić, czy ta metoda eval'd istnieje, będziesz chciał użyć typeof i ciągu funkcji wewnątrz eval :

var functionString = "nonexsitantFunction"
eval("typeof " + functionString) // returns "undefined" or "function"

Nie odwracaj tego i wypróbuj typof na eval . Jeśli to zrobisz, zostanie wygenerowany błąd ReferenceError:

var functionString = "nonexsitantFunction"
typeof(eval(functionString)) // returns ReferenceError: [function] is not defined

21
eval == evil;)
Yeti

1
Może to być złe, ale jest to bardzo pomocne, gdy nazwa funkcji znajduje się w zmiennej.
Luke Cousins,

8
Możesz to zrobić bez ewaluacji. Przykład:var a = 'alert'; window[a]('it works');
zennin,

15

Co powiesz na:

if('functionName' in Obj){
    //code
}

na przykład

var color1 = new String("green");
"length" in color1 // returns true
"indexOf" in color1 // returns true
"blablabla" in color1 // returns false

lub jak w twoim przypadku:

if('onChange' in me){
    //code
}

Zobacz dokumenty MDN .


ale to rozwiązanie nie działa za każdym razem :( na przykład, jeśli chcę wiedzieć, że jest lastIndexOf()w łańcuchu (wiemy, to znaczy, ale teoretycznie) typeof String().lastIndexOf === "function"to prawda, ale 'lastIndexOf' in Stringfałsz.
iiic

10

Spróbuj typeof- poszukaj 'undefined', że 'function'funkcja nie istnieje . JSFiddle dla tego kodu

function thisishere() {
    return false;
}
alert("thisishere() is a " + typeof thisishere);
alert("thisisnthere() is " + typeof thisisnthere);

Lub jako:

if (typeof thisishere === 'function') {
    // function exists
}

Lub z wartością zwracaną w jednym wierszu:

var exists = (typeof thisishere === 'function') ? "Value if true" : "Value if false";
var exists = (typeof thisishere === 'function') // Returns true or false

9

Nie widziałem tego sugerowanego: me.onChange && me.onChange (str);

Zasadniczo, jeśli me.onChange jest niezdefiniowany (co będzie, jeśli nie został zainicjowany), to nie wykona drugiej części. Jeśli me.onChange jest funkcją, wykona me.onChange (str).

Możesz nawet pójść dalej i zrobić:

me && me.onChange && me.onChange(str);

w przypadku gdy ja też jestem asynchroniczny.


5
//Simple function that will tell if the function is defined or not
function is_function(func) {
    return typeof window[func] !== 'undefined' && $.isFunction(window[func]);
}

//usage

if (is_function("myFunction") {
        alert("myFunction defined");
    } else {
        alert("myFunction not defined");
    }

twoje rozwiązanie nie jest jasne, ponieważ zawiera jQUery, co wydaje się dziwne w tej chwili, więc rzuca błędy podczas prostego testowania.
T.Todua

@tazotodua jest to funkcja samoobjaśniająca. jeśli chcesz używać bez jquery. wystarczy usunąć część &&. jest to dodatkowy warunek do sprawdzenia i uniknięcia błędów.
Muhammad Tahir

Czy stan po lewej stronie &&zajmuje coś, czego jQuery nie znajduje isFunctionsię po prawej stronie &&?
SantiBailors

5

Dla mnie najprostszy sposób:

function func_exists(fname)
{
  return (typeof window[fname] === 'function');
}

to jest poprawna odpowiedź, ponieważ jest to literał strunowy. Powiedziałbym, że tak jest lepiej, if ((typeof window["function_name"] !== 'undefined') && ((typeof window["function_name"] === 'function'))) { return true; } else { return false; }ale jest to drobna korekta
Pan Heelis

4

Pójdę o krok dalej, aby upewnić się, że właściwość jest rzeczywiście funkcją

function js_to_as( str ){
     if (me && me.onChange && typeof me.onChange === 'function') {
         me.onChange(str);
     }
}


3

Lubię używać tej metody:

function isFunction(functionToCheck) {
  var getType = {};
  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}

Stosowanie:

if ( isFunction(me.onChange) ) {
    me.onChange(str); // call the function with params
}


3
function function_exists(function_name)
{
    return eval('typeof ' + function_name) === 'function';
}
alert(function_exists('test'));
alert(function_exists('function_exists'));

LUB

function function_exists(func_name) {
  //  discuss at: http://phpjs.org/functions/function_exists/
  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: Steve Clay
  // improved by: Legaev Andrey
  // improved by: Brett Zamir (http://brett-zamir.me)
  //   example 1: function_exists('isFinite');
  //   returns 1: true

  if (typeof func_name === 'string') {
    func_name = this.window[func_name];
  }
  return typeof func_name === 'function';
}

1
Proszę o wyjaśnienie.
Gufran Hasan

W dwóch przypadkach wystarczy wywołać funkcję function_exists z nazwą parametru funkcji, aby sprawdzić istnienie, zwraca wartość bool.
Mohammad Lotfi,

3

Umieść podwójny wykrzyknik tj. !! przed nazwą funkcji, którą chcesz sprawdzić. Jeśli istnieje, zwróci wartość true.

function abc(){
}
!!window.abc; // return true
!!window.abcd; // return false

3

W kilku słowach: złap wyjątek.

Jestem naprawdę zaskoczony, że nikt jeszcze nie odpowiedział ani nie skomentował tego wyjątku.

Szczegół: Oto przykład, w którym próbuję dopasować funkcję, która jest poprzedzona maską i sufiksem w polu formularza „name”. Gdy JavaScript nie znajdzie tej funkcji, powinien zgłosić błąd ReferenceError, który możesz obsłużyć, jak chcesz, w sekcji catch.

function inputMask(input) {
  try {
    let maskedInput = eval("mask_"+input.name);

    if(typeof maskedInput === "undefined")
        return input.value;
    else
        return eval("mask_"+input.name)(input);

  } catch(e) {
    if (e instanceof ReferenceError) {
      return input.value;
    }
  }
}


2

Bez warunków

me.onChange=function(){};

function getID( swfID ){
     if(navigator.appName.indexOf("Microsoft") != -1){
          me = window[swfID];
     }else{
          me = document[swfID];
     }
}

function js_to_as( str ){
     me.onChange(str);
}

2

Podejrzewam, że menie jest poprawnie przypisywane obciążenie.

Przeniesienie wywołania get_ID do zdarzenia onclick powinno się tym zająć.

Oczywiście możesz dalej łapać pułapki, jak wspomniano wcześniej:

function js_to_as( str) {
  var me = get_ID('jsExample');
  if (me && me.onChange) {
    me.onChange(str);
  }
}

2

Zawsze sprawdzam tak:

if(!myFunction){return false;}

po prostu umieść go przed kodem korzystającym z tej funkcji


2

Miałem przypadek, w którym nazwa funkcji zmieniała się w zależności od zmiennej (w tym przypadku var 'x') dodanej do nazwy funkcji. To działa:

if ( typeof window['afunction_'+x] === 'function' ) { window['afunction_'+x](); } 


2

Próbowałem zaakceptować odpowiedź; jednak:

console.log(typeof me.onChange);

zwraca „niezdefiniowany”. Zauważyłem, że specyfikacja zawiera zdarzenie o nazwie „onchange” zamiast „onChange” (zwróć uwagę na camelCase).

Zmiana oryginalnej zaakceptowanej odpowiedzi na następującą działała dla mnie:

if (typeof me.onchange === "function") { 
  // safe to use the function
}

2

Jeśli szukasz funkcji, która jest wtyczką jQuery, musisz użyć funkcji $ .fn.myfunction

if (typeof $.fn.mask === 'function') {
    $('.zip').mask('00000');
}

2

Szukałem również eleganckiego rozwiązania tego problemu. Po długiej refleksji uznałem to podejście za najlepsze.

const func = me.onChange || (str => {}); func(str);


Jeśli dążysz do minimalizmu, możesz również to zrobić: (me.onChange||(_=>_))()Wykona funkcję, jeśli ona istnieje, w przeciwnym razie nic nie zrobi.
JSideris

Lepiej jest me.onChange && me.onChange()zapobiegać zdefiniowaniu funkcji void.
nekrofizowano

2

Nowoczesne Javascript na ratunek!

Może nie być to wielka szansa na zobaczenie z długą listą odpowiedzi, ale jest to teraz rozwiązane * na poziomie języka dzięki nowej składni Opcjonalnego Łączenia

me.onChange?.(str)

To takie proste - onChangewywoływane jest tylko wtedy, gdy istnieje .

Jeśli onChangenie istnieje, nic się nie dzieje, a wyrażenie powraca undefined- więc jeśli ma wartość zwracaną, której w innym przypadku użyłbyś, możesz po prostu sprawdzić tę wartość !== undefinedprzed kontynuowaniem.

Krawędź przypadek zastrzeżenie - jeśli onChange nie istnieje, ale to nie funkcja, to dostać TypeError. Jest to, jak można się spodziewać, to tak samo, jak próba wywołania dowolnej niefunkcji jako funkcji, ale warto wyraźnie zaznaczyć, że Opcjonalne Łączenie łańcuchów nie robi żadnej magii, aby to zniknęło.

* Cóż, technicznie rzecz biorąc Opcjonalne Łączenie jest nadal propozycją TC39 etapu 4, więc nie jest jeszcze w specyfikacji ECMAScript, ale etap 4 oznacza, że ​​jest sfinalizowany, a jego włączenie jest zasadniczo gwarantowane, po prostu czeka na nową wersję. Możesz użyć składni w jej ostatecznej wersji już dziś przez Babel, mając pewność, że się nie zmieni. Jest nawet w maszynopisie!


1

Oto działające i proste rozwiązanie do sprawdzania istnienia funkcji i dynamicznego uruchamiania tej funkcji przez inną funkcję;

Funkcja wyzwalania

function runDynamicFunction(functionname){ 

    if (typeof window[functionname] == "function") { //check availability

        window[functionname]("this is from the function it"); // run function and pass a parameter to it
    }
}

i możesz teraz generować funkcję dynamicznie, być może używając php w ten sposób

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

teraz możesz wywołać funkcję za pomocą dynamicznie generowanego zdarzenia

<?php

$name_frm_somware ="runThis_func";

echo "<input type='button' value='Button' onclick='runDynamicFunction(\"".$name_frm_somware."\");'>";

?>

dokładnie taki kod HTML, jakiego potrzebujesz

<input type="button" value="Button" onclick="runDynamicFunction('runThis_func');">

0
    function sum(nb1,nb2){

       return nb1+nb2;
    }

    try{

      if(sum() != undefined){/*test if the function is defined before call it*/

        sum(3,5);               /*once the function is exist you can call it */

      }

    }catch(e){

      console.log("function not defined");/*the function is not defined or does not exists*/
    }

0

A potem jest to ...

( document.exitPointerLock || Function )();

cześć Mistrzyni, dobra, ale co sądzisz o uchwyceniu wyjątku? sprawdź moją odpowiedź
Matteus Barbosa

Cześć dzięki za notatkę. Twoje rozwiązanie jest godne podziwu. Staram się unikać paradygmatu „spróbuj złapać”, gdy tylko jest to możliwe lub łatwiejsze, a może zostało to zasugerowane / narzucone przez pomoc strony trzeciej. „Ewaluacja” jest również niezadowolona z różnych powodów, z których jeden przypomina próbę złapania innego opakowania, więc opóźnienia są opóźnione. Istnieją alternatywy dla eval, które mogłyby „rzucić”. Myślę, że „nowa funkcja (parms, body)” może rzucić ci błąd, ale wydaje mi się, że kolejnym pytaniem dla mnie są porównania prędkości, inne niż po prostu najlepsza redukcja rozmiaru kodu (oznacza to dla mnie szybsze). [Hmm, to wygląda na nowe. Nie próbowałem tego jsben.ch]
Master James

mmm interesujący punkt na temat wywołania nowej funkcji zamiast tego. prześlij sugestie zmian do mojej odpowiedzi. wielkie dzięki
Matteus Barbosa

Tak, nawet w bash przy użyciu „source myScript.sh” pozwoli ci „eksportować” poprzez aliasy itp. To tak, jakby klasy i biblioteki zawsze były nieodłączną właściwością każdego kodu. Powinieneś mieć kod sprawdzający interpretera js, jeśli na pewno nie został usankcjonowany. Zbudowałem jeden w jednej funkcji, co jest kolejnym zabawnym wyzwaniem, które pomaga zrozumieć najprostszą aksjomatyczną naturę kodu, a nawet czas działania nie jest poza zasięgiem nikogo.
Mistrz James

0

Spróbuj tego:

Window.function_exists=function(function_name,scope){
//Setting default scope of none is provided
If(typeof scope === 'undefined') scope=window;
//Checking if function name is defined
If (typeof function_name === 'undefined') throw new 
Error('You have to provide an valid function name!');
//The type container
var fn= (typeof scope[function_name]);
//Function type
If(fn === 'function') return true;
//Function object type
if(fn.indexOf('function')!== false) return true; 
return false;
}

Pamiętaj, że napisałem to na telefonie komórkowym Może zawierać pewne duże litery i / lub inne niezbędne poprawki, takie jak na przykład nazwa funkcji

Jeśli chcesz, aby funkcja taka jak PHP sprawdzała, czy ustawiony jest var:

Window.isset=function (variable_con){
If(typeof variable_con !== 'undefined') return true;
return false;
}

0

Aby zilustrować poprzednie odpowiedzi, tutaj krótki fragment kodu JSFiddle:

function test () {
console.log()

}

console.log(typeof test) // >> "function"

// implicit test, in javascript if an entity exist it returns implcitly true unless the element value is false as :
// var test = false
if(test){ console.log(true)}
else{console.log(false)}

// test by the typeof method
if( typeof test === "function"){ console.log(true)}
else{console.log(false)}


// confirm that the test is effective : 
// - entity with false value
var test2 = false
if(test2){ console.log(true)}
else{console.log(false)}

// confirm that the test is effective :
// - typeof entity
if( typeof test ==="foo"){ console.log(true)}
else{console.log(false)}

/* Expected :
function
true 
true 
false
false
*/


0
// just pass your tested function name instead of myFunctionName
if ( $.isFunction($.fn.myFunctionName) ) {
    console.log( 'write your code here.' );
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.