Testen, ob der Wert eine Funktion ist

86

Ich muss testen, ob der Wert eines Formulars onsubmiteine Funktion ist. Das Format ist normalerweise onsubmit="return valid();". Gibt es eine Möglichkeit festzustellen, ob dies eine Funktion ist und ob sie aufrufbar ist? Die Verwendung von typeof gibt nur zurück, dass es sich um eine Zeichenfolge handelt, was mir nicht viel hilft.

EDIT : Natürlich verstehe ich, dass "return valid ();" ist eine Zeichenfolge. Ich habe replacees auf "valid ();" und sogar auf "valid ()" reduziert. Ich möchte wissen, ob eine davon eine Funktion ist.

EDIT : Hier ist ein Code, der mein Problem erklären kann:

$("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 : Hier ist der neue Code. Es scheint, dass ich immer noch eine Auswertung verwenden muss, da der Aufruf von form.submit () keine vorhandenen Onsubmits auslöst.

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

Vorschläge, wie dies möglicherweise besser gemacht werden kann?

Glen Solsberry
quelle

Antworten:

82

Ich ersetze eine Senden-Schaltfläche durch einen Anker-Link. Da der Aufruf von form.submit () onsubmit's nicht aktiviert, finde ich es und bewerte es selbst. Aber ich möchte überprüfen, ob die Funktion vorhanden ist, bevor ich nur bewerte, was da ist. - 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>

BEARBEITEN: Fehlender Parameter f in der Funktion testOnsubmitAndSubmit

Dies sollte unabhängig davon funktionieren, ob Sie das onsubmitHTML-Attribut oder in JavaScript zuweisen:

document.forms['theForm'].onsubmit = onsubmitHandler;
Grant Wagner
quelle
1
Woher kommt f in f.onsubmit?
Art
fist eine Formularinstanz. Sie übergeben es als Argument an die Funktion testOnsubmitAndSubmit. (Ich weiß, dass diese Frage ziemlich alt ist, aber vielleicht spart meine Antwort jemandem etwas Zeit :))
Zeroos
59

Versuchen

if (this.onsubmit instanceof Function) {
    // do stuff;
}
artemb
quelle
7
Das ist nur ein Beispiel. Sie können es in button.onsubmit Instanz der Funktion
ändern
13

Sie können den typeofOperator einfach zusammen mit einem ternären Operator verwenden:

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

Wenn es sich um eine Funktion handelt, rufen wir sie auf und geben ihren Rückgabewert zurück, andernfalls geben Sie einfach zurück true

Bearbeiten:

Ich bin mir nicht ganz sicher, was Sie wirklich tun möchten, aber ich werde versuchen zu erklären, was passieren könnte.

Wenn Sie Ihren onsubmitCode in Ihrem HTML-Code deklarieren , wird er in eine Funktion umgewandelt und kann daher von der JavaScript- "Welt" aufgerufen werden. Das bedeutet, dass diese beiden Methoden gleichwertig sind:

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

Diese beiden sind beide Funktionen und beide können aufgerufen werden. Sie können alle mit dem typeofOperator testen, der das gleiche Ergebnis erzielen soll : "function".

Wenn Sie der Eigenschaft "onsubmit" über JavaScript eine Zeichenfolge zuweisen, bleibt diese eine Zeichenfolge und kann daher nicht aufgerufen werden. Beachten Sie, dass, wenn Sie den typeofOperator dagegen anwenden , Sie "string"stattdessen erhalten "function".

Ich hoffe, dies könnte einige Dinge klarstellen. Wenn Sie jedoch wissen möchten, ob eine solche Eigenschaft (oder eine Kennung für die Angelegenheit) eine Funktion ist und aufgerufen werden kann, sollte der typeofBediener den Trick ausführen. Obwohl ich nicht sicher bin, ob es über mehrere Frames hinweg richtig funktioniert.

Prost

Pablo Cabrera
quelle
Ich muss dies jedoch außerhalb des Onsubmit testen.
Glen Solsberry
5

Welchen Browser verwenden Sie?

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

Dies gibt mir " function" in IE7 und FireFox.

Greg
quelle
Auch wenn Ihr Onsubmit "return valid ();" ist?
Glen Solsberry
1
Ja - vergessen Sie nicht, dass Sie außerhalb einer Funktion nicht "zurückkehren" können.
Greg
form.onsubmit ist immer eine Funktion, solange sie als HTML-Attribut definiert ist. Siehe meine Antwort.
Ionuț G. Stan
4

Verwenden einer stringbasierten Variablen als Beispiel und Verwenden instanceof Function Sie Sie registrieren die Funktion. Weisen Sie die Variable zu. Überprüfen Sie, ob die Variable der Name der Funktion ist. Führen Sie eine Vorverarbeitung durch. Weisen Sie die Funktion einer neuen Variablen zu. Dann Rufen Sie die Funktion auf.

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();
}
CrandellWS
quelle
2
Sie brauchen diese fn-Variable nicht wirklich, Sie könnten einfach window [value] () verwenden;
Lajos Meszaros
1
Ja, ich weiß, aber mir ist auch klar, dass es im Allgemeinen einfacher ist, es in einem langen Format zu verstehen, und da dies in erster Linie eine Website zum Lernen Ihrer Eingaben ist, wird es auf jeden Fall geschätzt @LajosMeszaros
CrandellWS
3

Stellen Sie sicher, dass Sie typeof für die eigentliche Funktion aufrufen, nicht für ein Zeichenfolgenliteral:

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

typeof "x"; // returns "string"

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

Sie können versuchen, diese Technik an Ihre Bedürfnisse anzupassen:

 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.');
 }
Cletus
quelle
2

form.onsubmit ist immer eine Funktion, wenn es als Attribut von HTML das Formularelement definiert. Es handelt sich um eine anonyme Funktion, die an ein HTML-Element angehängt ist. Der Zeiger this ist an dieses FORM-Element gebunden, und es gibt einen Parameter mit dem Namen, eventder Daten zum Submit-Ereignis enthält.

Unter diesen Umständen verstehe ich nicht, wie Sie als Ergebnis einer Operation eine Zeichenfolge erhalten haben. Sie sollten mehr Details angeben, besser etwas Code.

Bearbeiten (als Antwort auf Ihre zweite Bearbeitung):

Ich glaube, dass der an das HTML-Attribut angehängte Handler unabhängig vom obigen Code ausgeführt wird. Außerdem könnten Sie versuchen, es irgendwie zu stoppen, aber es scheint, dass FF 3, IE 8, Chrome 2 und Opera 9 zuerst den HTML-Attribut-Handler und dann den angehängten ausführen (ich habe nicht mit jQuery getestet zwar, aber mit addEventListener und attachEvent). Also ... was versuchst du genau zu erreichen?

Ihr Code funktioniert übrigens nicht, weil Ihr regulärer Ausdruck die Zeichenfolge "valid ();" extrahiert, was definitiv keine Funktion ist.

Ionuț G. Stan
quelle
2

Wenn es sich um eine Zeichenfolge handelt, können Sie davon ausgehen, dass sie immer die Form hat

return SomeFunction(arguments);

Analysieren Sie den Funktionsnamen und prüfen Sie, ob diese Funktion mit definiert ist

if (window[functionName]) { 
    // do stuff
}
Millimoose
quelle
Ich wollte auch diese Auflösung hinzufügen ... Denken Sie daran, die Funktion auf Dokument- / Fensterebene zu registrieren
CrandellWS
1

Nun, "return valid();" ist eine Zeichenfolge, also ist das richtig.

Wenn Sie überprüfen möchten, ob stattdessen eine Funktion angehängt ist, können Sie Folgendes versuchen:

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

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

Ich denke, die Quelle der Verwirrung ist die Unterscheidung zwischen dem Attribut eines Knotens und der entsprechenden Eigenschaft .

Sie verwenden:

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

Sie lesen direkt das onsubmit Attribut ‚s - Wert (das muss ein String sein). Stattdessen sollten Sie auf die onsubmit Eigenschaft des Knotens zugreifen :

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

Hier ist ein kurzer Test:

<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> 

Dies ergibt:

form1 onsubmit-Eigenschaft: (Funktion) Funktion onsubmit (Ereignis) {return valid (); }}
form1 onsubmit-Attribut: (string) return valid ()
Ates Goral
quelle
1
  if ( window.onsubmit ) {
     //
  } else {
     alert("Function does not exist.");
  }
TStamper
quelle
0

Sie können immer eine der typeOf-Funktionen in JavaScript-Blogs wie Chris Wests verwenden . Die Verwendung einer Definition wie der folgenden für die typeOf()Funktion würde funktionieren:

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

Diese Funktion (die im globalen Namespace deklariert ist, kann folgendermaßen verwendet werden:

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

Wenn es sich um eine Funktion handelt, wird "Funktion" zurückgegeben. Wenn es sich um eine Zeichenfolge handelt, wird "Zeichenfolge" zurückgegeben. Andere mögliche Werte werden hier angezeigt .

Xavier Botomon
quelle
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
    }
}
Konrad Borowski
quelle
-3

Eine einfache Überprüfung wie diese zeigt an, ob sie vorhanden / definiert ist:

if (this.onsubmit)
{
  // do stuff;
}
Kon
quelle
6
Das wird nicht funktionieren. Das if wird auf TRUE gesetzt, wenn onsubmit ebenfalls eine nicht leere Zeichenfolge ist.
Seb
1
Eine schreckliche Art zu testen, ob etwas eine Funktion ist - wie angegeben, und um es klarer zu machen: Alles, was "wahr" ist, würde dazu führen, dass dieser Code "Sachen macht", und das ist möglicherweise nicht das, was erwartet wird. Wenn this.onsubmit auf den Wert 5 oder "Hallo" oder etwas anderes in JavaScript gesetzt wurde, das als wahr ausgewertet wird, tritt unerwartetes Verhalten auf.
Jason Bunting
Das Thema der Frage fragt, wie überprüft werden soll, ob etwas vorhanden ist. Das ist alles, was ich vorgeschlagen habe - nicht mehr und nicht weniger.
Kon
Nicht wirklich - das Original besagt, dass er "testen muss, ob der Wert des Onsubmit eines Formulars eine Funktion ist". Ihr Zustand ist nicht, ob dies eine Funktion ist oder nicht. Ihr Test fragt einfach, ob diese Vorlage "wahr" ist oder nicht
Jason Bunting