web-dev-qa-db-ja.com

値が関数かどうかのテスト

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

[〜#〜] edit [〜#〜]:もちろん、「return valid();」と理解しています文字列です。私はreplacedを「valid();」、さらには「valid()」にまで下げました。どちらかが関数かどうか知りたいです。

[〜#〜] edit [〜#〜]:ここにいくつかのコードがあります。これは私の問題を説明するのに役立つでしょう:

$("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;
    }
} );

EDIT 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;
    }
} );

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

84
Glen Solsberry

送信ボタンをアンカーリンクに置き換えています。 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がありません

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

document.forms['theForm'].onsubmit = onsubmitHandler;
79
Grant Wagner

試して

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

簡単にtypeof演算子と三項演算子を使用できます:

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

関数の場合は呼び出して戻り値を返し、そうでない場合は単にtrueを返します

編集:

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

Html内でonsubmitコードを宣言すると、関数に変換され、JavaScriptの「世界」から呼び出し可能になります。つまり、これら2つの方法は同等です。

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

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

これで、JavaScriptを使用して「onsubmit」プロパティに文字列を割り当てると、文字列のままになるため、呼び出しできません。 typeof演算子を適用すると、"string" の代わりに "function"

これでいくつかのことが明らかになることを願っています。この場合も、そのようなプロパティ(または問題の識別子)が関数で呼び出し可能かどうかを知りたい場合は、typeof演算子を使用する必要があります。複数のフレームで適切に動作するかどうかはわかりませんが。

乾杯

12
Pablo Cabrera

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

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

これにより、IE7およびFireFoxで「function」が得られます。

5
Greg

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

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

typeof "x"; // returns "string"

typeof x; // returns "function"
3
matt b

必要に応じて この手法 を変更してみてください:

 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.');
 }
3
cletus

文字列ベースの変数を例として使用し、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();
}
3
CrandellWS

form.onsubmitは、フォーム要素のHTMLの属性として定義されている場合、常に関数になります。これは、HTML要素に付加された匿名関数の一種であり、そのFORM要素にバインドされたthisポインターを持ち、eventこれには、送信イベントに関するデータが含まれます。

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

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

HTML属性に関連付けられたハンドラーは、上記のコードに関係なく実行されると思います。さらに、どうにかして停止しようとすることもできますが、FF 3 IE 8、Chrome 2 and Opera 9は最初にHTML属性ハンドラーを実行し、次にアタッチされたハンドラーを実行しています(ただし、jQueryではテストしませんでしたが、addEventListenerおよびattachEventでテストしました)。

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

2
Ionuț G. Stan

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

return SomeFunction(arguments);

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

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

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

あなたが使用しています:

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

onsubmitattributeの値(mustは文字列)を直接読み取っています。代わりに、ノードのonsubmitpropertyにアクセスする必要があります。

$("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)function onsubmit(event){return valid(); } 
 form1 onsubmit属性:(string)return valid()
1
Ates Goral

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

代わりに関数がアタッチされているかどうかを確認したい場合、これを試すことができます:

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

if(typeof formId.onsubmit == "function"){
  alert("it's a function!");
}
1
Seb
  if ( window.onsubmit ) {
     //
  } else {
     alert("Function does not exist.");
  }
1
TStamper

Chris West's などのJavaScriptブログでは、いつでもtypeOf関数の1つを使用できます。 typeOf()関数に次のような定義を使用すると機能します。

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

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

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

関数の場合、「関数」が返されます。文字列の場合、「String」が返されます。他の可能な値は here で示されています。

0
Xavier Botomon
// 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
    }
}
0
Konrad Borowski