値が関数であるかどうかのテスト


88

フォームの値がonsubmit関数であるかどうかをテストする必要があります。通常、形式はonsubmit="return valid();"です。これが関数であるかどうか、そしてそれが呼び出し可能かどうかを判断する方法はありますか?typeofを使用すると、それが文字列であることが返されるだけで、あまり役に立ちません。

編集:もちろん、私は「returnvalid();」を理解しています。文字列です。私はreplaceそれを「valid();」、さらには「valid()」にまで絞り込みました。どちらかが機能なのか知りたいです。

編集:これが私の問題を説明するのに役立つかもしれないいくつかのコードです:

$("a.button").parents("form").submit(function() {
    var submit_function = $("a.button").parents("form").attr("onsubmit");
    if ( submit_function && typeof( submit_function.replace(/return /,"") ) == 'function' ) {
        return eval(submit_function.replace(/return /,""));
    } else {
        alert("onSubmit is not a function.\n\nIs the script included?"); return false;
    }
} );

編集2:これが新しいコードです。form.submit()を呼び出しても既存のonsubmitは起動されないため、まだevalを使用する必要があるようです。

var formObj = $("a.button").parents("form");
formObj.submit(function() {
    if ( formObj[0].onsubmit && typeof( formObj.onsubmit ) == 'function' ) {
        return eval(formObj.attr("onsubmit").replace(/return /,""));
    } else {
        alert("onSubmit is not a function.\n\nIs the script included?");
        return false;
    }
} );

おそらくこれをより良くする方法についての提案?

回答:


85

送信ボタンをアンカーリンクに置き換えています。form.submit()を呼び出してもonsubmitがアクティブにならないので、私はそれを見つけて、自分でeval()します。しかし、そこにあるものをeval()する前に、関数が存在するかどうかを確認したいと思います。– gms8994

<script type="text/javascript">
function onsubmitHandler() {
    alert('running onsubmit handler');
    return true;
}
function testOnsubmitAndSubmit(f) {
    if (typeof f.onsubmit === 'function') {
        // onsubmit is executable, test the return value
        if (f.onsubmit()) {
            // onsubmit returns true, submit the form
            f.submit();
        }
    }
}
</script>

<form name="theForm" onsubmit="return onsubmitHandler();">
<a href="#" onclick="
    testOnsubmitAndSubmit(document.forms['theForm']);
    return false;
"></a>
</form>

編集:関数testOnsubmitAndSubmitにパラメーターfがありません

上記は、onsubmitHTML属性を割り当てるか、JavaScriptで割り当てるかに関係なく機能するはずです。

document.forms['theForm'].onsubmit = onsubmitHandler;

1
f.onsubmitのfはどこから来たのですか?
アート

fフォームインスタンスです。これを引数としてtestOnsubmitAndSubmit関数に渡します。(私はこの質問がかなり古いことを知っていますが、おそらく私の答えは誰かの時間を節約するでしょう:))
zeroos 2012年

63

試してみてください

if (this.onsubmit instanceof Function) {
    // do stuff;
}

7
これは単なるサンプルです。これをbutton.onsubmitinstanceof Functionに変更できます
artemb 2009

13

単純に、typeof演算子を三項演算子と一緒に使用できます。

onsubmit="return typeof valid =='function' ? valid() : true;"

関数の場合は呼び出して戻り値を返します。それ以外の場合は単に true

編集:

あなたが本当に何をしたいのかよくわかりませんが、何が起こっているのかを説明しようと思います。

onsubmitHTML内でコードを宣言すると、コードは関数に変換されるため、JavaScriptの「ワールド」から呼び出すことができます。つまり、これら2つの方法は同等です。

HTML: <form onsubmit="return valid();" />
JavaScript: myForm.onsubmit = function() { return valid(); };

これら2つは両方とも関数であり、両方とも呼び出し可能です。typeof同じ結果が得られるはずの演算子を使用して、これらのいずれかをテストできます"function"

これで、JavaScriptを介して「onsubmit」プロパティに文字列を割り当てると、文字列のままになるため、呼び出すことができなくなります。typeof演算子を適用すると、の"string"代わりに取得されることに注意してください"function"

これでいくつかのことが明らかになることを願っています。繰り返しになりますが、そのようなプロパティ(または問題の識別子)が関数であり、呼び出し可能であるかどうかを知りたい場合は、typeofオペレーターがそのトリックを実行する必要があります。複数のフレームで正しく機能するかどうかはわかりませんが。

乾杯


ただし、onsubmitの外でこれをテストする必要があります。
グレンソルズベリー2009

5

どのブラウザを使用していますか?

alert(typeof document.getElementById('myform').onsubmit);

これによりfunction、IE7とFireFoxで「」が表示されます。


onsubmitが「returnvalid();」であっても?
グレンソルズベリー2009

1
はい-忘れないでください。関数の外に「戻る」ことはできません。
グレッグ

form.onsubmitは、HTML属性として定義されている限り、常に関数になります。私の答えを見てください。
Ionuț G. Stan

4

文字列ベースの変数を例として使用し、使用 instanceof Function する関数を登録します。変数を割り当てます...変数が関数の名前であることを確認します...前処理を行います...関数を新しい変数に割り当てます...次に関数を呼び出します。

function callMe(){
   alert('You rang?');
}

var value = 'callMe';

if (window[value] instanceof Function) { 
    // do pre-process stuff
    // FYI the function has not actually been called yet
    console.log('callable function');
    //now call function
   var fn = window[value];
   fn();
}

2
そのfn変数は実際には必要ありません。window[value]();を使用するだけで済みます。
ラヨシュメサロス2016年

1
いや、私は知っているが、私はまた、一般的に、長い形式で分かりやすく、このよう主にご入力は任意のケース@LajosMeszarosに評価される学習のためのサイトであることを実感
CrandellWS

3

文字列リテラルではなく、実際の関数でtypeofを呼び出していることを確認してください。

function x() { 
    console.log("hi"); 
}

typeof "x"; // returns "string"

typeof x; // returns "function"

3

ニーズに合わせてこの手法を変更しみてください。

 function isFunction() {
   var functionName = window.prompt('Function name: ');
   var isDefined = eval('(typeof ' + functionName + '==\'function\');');
   if (isDefined)
     eval(functionName + '();');
   else
     alert('Function ' + functionName + ' does not exist');
 }
 function anotherFunction() {
   alert('message from another function.');
 }

2

form.onsubmitは、フォーム要素のHTMLの属性として定義されている場合、常に関数になります。これは、HTML要素にアタッチされたある種の無名関数であり、このポインターがそのFORM要素にバインドされてeventおり、送信イベントに関するデータを含むという名前のパラメーターもあります。

このような状況では、ある種の操作の結果としてどのように文字列を取得したのかわかりません。あなたはより多くの詳細、より良いいくつかのコードを与えるべきです。

編集(2回目の編集への応答として):

上記のコードに関係なく、HTML属性にアタッチされたハンドラーが実行されると思います。さらに、なんとかしてやめようとすることもできますが、FF 3、IE 8、Chrome 2、Opera 9が最初にHTML属性ハンドラーを実行してから、添付されたものを実行しているようです(jQueryでテストしていません)ただし、addEventListenerとattachEventを使用します)。それで...あなたは正確に何を達成しようとしていますか?

ちなみに、正規表現は文字列「valid();」を抽出するため、コードは機能していません。これは間違いなく関数ではありません。


2

文字列の場合は、常に次の形式であると想定/希望できます。

return SomeFunction(arguments);

関数名を解析し、その関数がを使用して定義されているかどうかを確認します

if (window[functionName]) { 
    // do stuff
}

私もこの解像度を追加しようとしていました...ドキュメント/ウィンドウレベルで関数を登録することを忘れないでください
CrandellWS 2014

1

まあ、それ"return valid();" 文字列なので、それは正しいです。

代わりに関数がアタッチされているかどうかを確認したい場合は、次のことを試してください。

formId.onsubmit = function (){ /* */ }

if(typeof formId.onsubmit == "function"){
  alert("it's a function!");
}

1

混乱の原因は、ノードの属性と対応するプロパティの違いだと思います

使用しているもの:

$("a.button").parents("form").attr("onsubmit")

onsubmit 属性の値(文字列である必要があります)を直接読み取っています。代わりに、ノードのonsubmit プロパティにアクセスする必要があります。

$("a.button").parents("form").prop("onsubmit")

簡単なテストは次のとおりです。

<form id="form1" action="foo1.htm" onsubmit="return valid()"></form>
<script>
window.onload = function () {
    var form1 = document.getElementById("form1");

    function log(s) {
        document.write("<div>" + s + "</div>");
    }

    function info(v) {
        return "(" + typeof v + ") " + v;
    }

    log("form1 onsubmit property: " + info(form1.onsubmit));
    log("form1 onsubmit attribute: " + info(form1.getAttribute("onsubmit")));
};
</script> 

これにより、次のようになります。

form1 onsubmitプロパティ:(関数)function onsubmit(event){return valid(); }
form1 onsubmit属性:(文字列)return valid()


1

typeof xxx === 'function'最高で最速ではありませんか?

instanceofや_underscoreと比較して、試してみることができるベンチを作りました

  1. そのはinstanceof(クロムを使用)よりも速いようです
  2. 変数が定義されていない場合、エラーは発生しません

ここにベンチがあります:https//jsbench.me/qnkf076cqb/1


0

あなたはいつものようなJavaScriptのブログにtypeof演算機能のいずれかを使用することができクリス西さんtypeOf()関数に次のような定義を使用すると機能します。

function typeOf(o){return {}.toString.call(o).slice(8,-1)}

この関数(グローバル名前空間で宣言されている)は、次のように使用できます。

alert("onsubmit is a " + typeOf(elem.onsubmit));

関数の場合は「関数」が返されます。文字列の場合は「文字列」が返されます。その他の可能な値をここに示します


0
// This should be a function, because in certain JavaScript engines (V8, for
// example, try block kills many optimizations).
function isFunction(func) {
    // For some reason, function constructor doesn't accept anonymous functions.
    // Also, this check finds callable objects that aren't function (such as,
    // regular expressions in old WebKit versions), as according to EcmaScript
    // specification, any callable object should have typeof set to function.
    if (typeof func === 'function')
        return true

    // If the function isn't a string, it's probably good idea to return false,
    // as eval cannot process values that aren't strings.
    if (typeof func !== 'string')
        return false

    // So, the value is a string. Try creating a function, in order to detect
    // syntax error.
    try {
        // Create a function with string func, in order to detect whatever it's
        // an actual function. Unlike examples with eval, it should be actually
        // safe to use with any string (provided you don't call returned value).
        Function(func)
        return true
    }
    catch (e) {
        // While usually only SyntaxError could be thrown (unless somebody
        // modified definition of something used in this function, like
        // SyntaxError or Function, it's better to prepare for unexpected.
        if (!(e instanceof SyntaxError)) {
            throw e
        }

        return false
    }
}

-3

このような簡単なチェックにより、存在/定義されているかどうかがわかります。

if (this.onsubmit)
{
  // do stuff;
}

6
これは機能しません。onsubmitが空でない文字列の場合も、ifはTRUEをアサートします。
セブ

1
何かが関数であるかどうかをテストする恐ろしい方法-示されているように、そしてより明確に:「真実」であると、このコードは「何かをする」ことになり、それは期待されたものではないかもしれません。this.onsubmitが5の値、「hello」、またはtrueと評価されるJavaScriptの他の値に設定されている場合、予期しない動作が発生します。
ジェイソンバンティング

質問の主題は、何かが存在するかどうかを確認する方法を尋ねます。私が提案したのはそれだけです-それ以上でもそれ以下でもありません。
Kon

実際にはそうではありません-元の投稿には、「フォームのonsubmitの値が関数であるかどうかをテストする必要がある」と記載されています。あなたの条件はthis.onsubmitが関数であるかどうかではなく、あなたのテストは単にthis.onsubmitが「真実」であるかどうかを尋ねます
Jason Bunting
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.