JavaScript関数が定義されているかどうかを確認する方法


302

JavaScriptの関数が定義されているかどうかはどのようにしてわかりますか?

このようなことをしたい

function something_cool(text, callback) {
    alert(text);
    if( callback != null ) callback();
}

しかし、それは私を取得します

コールバックは関数ではありません

コールバックが定義されていない場合のエラー。

回答:


475
typeof callback === "function"

47
typeof値のセットはECMA仕様で正確に定義されているため、これは実際には魔法の文字列ではありません。これの構文は、最初は少し間抜けですが、完全に合理的な慣用的なJavascriptです。
Ben Zotto

2
@quixoto-わかりました、つまり、文字列が必要であるということです-絶対に必要なものよりもコードを散らかすリテラル文字列はありません。したがって、何かが関数であるかどうかをテストする場合、これは私の理想ではありません。
Jason Bunting 2010

4
そして、そうです、「マジック」は、ずさんな、言葉の選択が悪かったのです。つまり、「マジックストリング」ではなく、「リテラルストリング」を意味しました。私の悪い。:)
Jason Bunting 2010年


関数のかっこを削除して、if条件でのみ関数名を使用してください。そうしないと、trueまたはfalseを返す代わりに関数が呼び出されます。
ラッセルシュトラウス

236

現在のすべての回答はリテラル文字列を使用していますが、可能であればコードに含めないようにします-これはそうではありません(ブートするための意味的な意味を提供します)。

function isFunction(possibleFunction) {
  return typeof(possibleFunction) === typeof(Function);
}

個人的には、コードにぶら下がっている文字列の数を減らすようにしています...


また、私はそれtypeofが関数ではなく演算子であることを認識していますが、それを後者として表示する構文を使用してもほとんど害はありません。


7
この機能を使用するにはどうすればよいですか?定義されていない関数の名前がisFunction(not_defined))どこでnot_definedあるか試しましnot_defined is not definedたが、正しいFireBugが返されましたが、関数はfalseを返してエラーを生成しないはずです...
Wookie88

@ Wookie88:技術的に言えば、JavaScriptインタープリターがnot_definedその値を渡すためにシンボルを解決しようとしていて、そのisFunction()解決に失敗しているため、エラーが発生しても、私の回答に示されている関数はエラーを返しません。isFunction()この問題を解決するための定義に対して何もできません。
Jason Bunting 2012年

3
@ZacharyYates ReferenceErrorを回避する方法は、多分定義されていない関数への参照を使用しないようにすることを意味します。関数呼び出し内で型チェックを行い、結果を関数に渡すことができます。jsfiddle.net/qNaxJ多分それほど良くないかもしれませんが、少なくとも文字列は使用されません;)
netiul

8
または、関数isFunctionを避けて、単に行い(typeof no_function == typeof Function)ます。
netiul 2014年

2
@JasonBuntingうるさい場合typeof(Function())は、Functionが関数なので、実際に使用する必要 があります。ただし、配列、オブジェクト、およびその他の組み込みプロトタイプ(より適切な用語がないため)も同様です。たとえば、配列をチェックする場合は使用typeof(array) === typeof(Array)しません。typeof(array) === typeof(Array())注意と一貫性がある場合は、実際に関数を評価する必要があるので、これを使用します。
seanmhanson、2015年

16
if (callback && typeof(callback) == "function")

なお、コールバックに(単独で)を評価しfalse、それがある場合にundefinednull0、またはfalse。と比較することnullは非常に具体的です。


2
また、callbackそれ自体が「false-y」の値に評価される場合、そのtypeofが「関数」になることありません。
Joe

5
@Joe、ただし短絡のため、コールバックがfalseと評価された場合、そのテストは実行されません。
Fabio A.

3
最初の条件が例外をすぐに発生させるため、このソリューションは機能していません。オブジェクトのプロパティの場合、これは機能する可能性があります:if(obj.callback){...}
Roey

8

関数が実装されているかどうかを判断するこれらのメソッドは、変数が定義されていない場合も失敗するため、文字列の受信をサポートするより強力なものを使用しています。

function isFunctionDefined(functionName) {
    if(eval("typeof(" + functionName + ") == typeof(Function)")) {
        return true;
    }
}

if (isFunctionDefined('myFunction')) {
    myFunction(foo);
}

私は良い答えだと思います、あなたは正しいです、上記のすべてのメソッドは失敗します関数は定義されていません。
Matteo Conta 2013

未定義の参照を避けるのは簡単です-のtypeof window.doesthisexist代わりに単に参照してくださいdoesthisexist。ただし、示されているようにeval(これは悪です)を使用すると、名前付き関数でのみ機能します。これは、問題のユースケースでは機能しません。
AD7six 2013年

これはグローバルスコープでのみ機能しますが、受け入れられた回答はローカルスコープ機能でも機能することに注意してください。
inf3rno 2017年

6

JavaScriptの新機能動作が変更されたかどうかはわかりませんが、possibleFunctionが定義されていないと、Jason Bunting(6年前)によって提供されたソリューションが機能しません。

function isFunction(possibleFunction) {
  return (typeof(possibleFunction) == typeof(Function));
}

これはReferenceError: possibleFunction is not defined、エンジンが可能なシンボルを解決しようとするときにエラーをスローします(Jasonの回答へのコメントで言及されているように)

この動作を回避するには、存在するかどうかを確認する関数の名前のみを渡すことができます。そう

var possibleFunction = possibleFunction || {};
if (!isFunction(possibleFunction)) return false;

これにより、変数をチェックする関数に設定するか、定義されていない場合は空のオブジェクトに設定して、上記の問題を回避します。


明確にするために:私のコードはエラーをスローしません。それは、JavaScriptパーサーがそれを実行しているだけです。このような方法で未定義の識別子を使用しようとした場合も同じことが起こります。
Jason Bunting、2015年

6

試してください:

if (typeof(callback) == 'function')

こんにちは、「緩い」比較を使用しないでください(==)変数の型も比較する場合は、常に「===」を使用してください。
Joel Carneiro、

4
function something_cool(text, callback){
    alert(text);
    if(typeof(callback)=='function'){ 
        callback(); 
    };
}

4
if ('function' === typeof callback) ...

3
ビット知識をひけらかす、まだ文字列リテラルを使用しています。いかがif(typeof Function === typeof callback)...ですか?:)
Jason Bunting 2010年

@JasonBunting好奇心が強い、文字列リテラルの使用の何が問題になっていますか?
Bsienn

@Bsienn-私が言ったように、それは私についての知識ですが、ここにあります。あなたは、文字列リテラルとコード、およびへの呼び出しを使用しましょうtypeof、それは-理由はJavaScriptの新しい/異なる実装を、後で別のリターンの何か(代わりに「機能」のかもしれない「機能」)を感じて、それは可能性が低いことになりますように新しい/異なる実装はtypeof Function === typeof callback、セマンティックレベルで同じでなければならないため、チェックを破ります。
Jason Bunting 2017年


4

私はするかもしれません

try{
    callback();
}catch(e){};

受け入れられる答えがあることは知っていますが、誰もこれを提案しませんでした。これが慣用句の説明に当てはまるかどうかは本当にわかりませんが、すべてのケースで機能します。

新しいJavaScriptエンジンでは、finally代わりにを使用できます。


これはきちんとしたショートカットです!ただし、関数が存在するか定義されているかどうかをテストするだけでは機能しません(実行はしません)。
Beejor

それは本当だ。その実行ポイントでコールバックがオプションである状況を想定しました。typeof callbackとにかく普段使います。
Quentin Engles、2015

それは理にかなっている; 内容よりも題名に力を入れていました。何トンものテストにtry-catchを使用するシンプルさが好きな場合があります。これを使用することには、typeofのようなものに対して、技術的な欠点があると思いますか?それともそれは主により適切な/期待される方法で物事を行うことの問題ですか?
Beejor

1
複数のタイプをテストしたい場合、例外はあまり良くありません。たとえば、私が現在取り組んでいるプロジェクトでは、1つの変数に対して多くの型チェックを使用して、それが関数、文字列などであるかどうかを確認しています。このプロジェクトでは、タイプが本当に必要です。このために、型の配列を使用し、accepted_types.indexOf(typeof value) !== -1それが型の範囲内にあるかどうかを確認します。この状況では、例外は私の意見では禁止されます。
Quentin Engles

2

これを試して:

callback instanceof Function

1
動作しません。それでもエラーが発生します。回答として投稿する前に、自分で試してみてください。
vbullinger 2012

@vbullinger Chrome、Firefox、Safariでもう一度テストしたところ、どこでも動作します。どのエンジンで問題が発生しましたか?
eWolf 2012

Firefox。コールバックが定義されていないケースをテストしましたか?
vbullinger 2012

:働くことはありませんことを、あなたが直接、未定義の変数を参照しているためだとpastebin.com/UQz2AmzH
eWolf

3
関数パラメーターで使用すると機能します。これは、作成者が求めたものです。ECMAScriptは、存在しない変数と値が未定義の既存の変数のケースを区別すると思います。これについてもっと知ることは興味深いでしょう。
eWolf 2012

2

ライブラリのソース @Venkat Sudheer Reddy Aedama、underscorejsを見ると、次のことがわかります。

_.isFunction = function(obj) {
  return typeof obj == 'function' || false;
};

これは私のヒント、ヒントの答えです:>




1

jQuery関数が定義されているかどうかを確認する方法を探していましたが、簡単に見つかりませんでした。

おそらくそれが必要かもしれません;)

if(typeof jQuery.fn.datepicker !== "undefined")

type0f($.datepicker) !== undefiledそれ以外は同じobject
vladkras 2015

0

場合callback()は、関数に一度だけのためではない呼び出している、あなたは再利用のための引数を初期化できます。

callback = (typeof callback === "function") ? callback : function(){};

例えば:

function something_cool(text, callback) {
    // Initialize arguments
    callback = (typeof callback === "function") ? callback : function(){};

    alert(text);

    if (text==='waitAnotherAJAX') {
        anotherAJAX(callback);
    } else {
        callback();
    }
}

制限は、それが未定義であっても、常にコールバック引数を実行することです。


0

グローバル関数の場合eval、回答の1つで提案されている代わりにこれを使用できます。

var global = (function (){
    return this;
})();

if (typeof(global.f) != "function")
    global.f = function f1_shim (){
        // commonly used by polyfill libs
    };

あなたも使用できますglobal.f instanceof Functionが、afaik。の値はFunctionフレームによって異なるため、単一のフレームアプリケーションでのみ正しく機能します。そのため、通常はtypeof代わりに使用します。一部の環境では異常が発生する可能性があることに注意してくださいtypeof f。たとえば、MSIE 6〜8では、一部の関数にalert「オブジェクト」タイプが含まれていました。

ローカル関数により、受け入れられた答えの1つを使用できます。関数がローカルかグローバルかをテストすることもできます。

if (typeof(f) == "function")
    if (global.f === f)
        console.log("f is a global function");
    else
        console.log("f is a local function");

質問に答えるために、サンプルコードは最新のブラウザでエラーなしで機能しているため、何が問題であったのかわかりません。

function something_cool(text, callback) {
    alert(text);
    if( callback != null ) callback();
}

注:のcallback !== undefined代わりにを使用しますがcallback != null、ほとんど同じです。


0

以前のすべての回答とは限りませんが、ほとんどの場合、関数を呼び出す副作用があります

ここでのベストプラクティス

あなたは機能を持っています

function myFunction() {
        var x=1;
    }
それをテストする直接的な方法

//direct way
        if( (typeof window.myFunction)=='function')
            alert('myFunction is function')
        else
            alert('myFunction is not defined');
文字列を使用して、関数名を定義する場所を1つだけにすることができます

//byString
        var strFunctionName='myFunction'
        if( (typeof window[strFunctionName])=='function')
            alert(s+' is function');
        else
            alert(s+' is not defined');


0

関数を再定義する場合は、関数がどこで発生してもグローバルに定義されるため、関数変数を使用順に定義することをお勧めします。

同じ名前の以前の関数を呼び出す新しい関数を作成する例:

A=function() {...} // first definition
...
if (typeof A==='function')
   oldA=A;
A=function() {...oldA()...} // new definition


-2

ワンラインソリューション:

function something_cool(text, callback){
    callback && callback();
}

彼の例は、それが定義されている場合は関数が呼び出されることを望んでおり、定義されていない場合は何も起こらないことを示しています。jsfiddle.net/nh1cxxg6 falseまたはfalseの値を返す関数は引き続き呼び出されます。もちろん、これは値を返したい場合には機能しません。
Samir Alajmovic

ああ、私は彼の質問を誤解しました。ただし、コールバックが関数でない場合は、例外が発生します。
フランクブライス2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.