web-dev-qa-db-fra.com

Tester si la valeur est une fonction

Je dois tester si la valeur du onsubmit d'un formulaire est une fonction. Le format est généralement onsubmit="return valid();". Y a-t-il un moyen de savoir s'il s'agit d'une fonction et si elle est appelable? L'utilisation de typeof retourne simplement qu'il s'agit d'une chaîne, ce qui ne m'aide pas beaucoup.

EDIT : Bien sûr, je comprends que "return valid ();" est une chaîne. J'ai replaced en "valid ();" et même "valid ()". Je veux savoir si l'une ou l'autre de ces fonctions est une fonction.

EDIT : Voici du code, qui peut aider à expliquer mon problème:

$("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: Voici le nouveau code. Il semble que je doive toujours utiliser un eval, car appeler form.submit () ne déclenche pas les demandes existantes.

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

Suggestions sur comment mieux faire cela?

84
Glen Solsberry

Je remplace un bouton d'envoi par un lien d'ancrage. Comme appeler form.submit () n'active pas onsubmit, je le trouve et j'évalue () moi-même. Mais je voudrais vérifier si la fonction existe avant d’évaluer () ce qui est là. - 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>

EDIT: paramètre manquant dans la fonction testOnsubmitAndSubmit

Ce qui précède devrait fonctionner que vous affectiez ou non l'attribut HTML onsubmit HTML:

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

Essayer

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

Vous pouvez simplement utiliser l'opérateur typeof avec un opérateur ternaire:

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

Si c'est une fonction, on l'appelle et on retourne sa valeur de retour, sinon on retourne simplement true

Edit:

Je ne suis pas tout à fait sûr de ce que vous voulez vraiment faire, mais je vais essayer d'expliquer ce qui pourrait se passer.

Lorsque vous déclarez votre code onsubmit dans votre code HTML, il est transformé en une fonction et peut donc être appelé à partir du "monde" JavaScript. Cela signifie que ces deux méthodes sont équivalentes:

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

Ces deux seront les deux fonctions et les deux seront appelables. Vous pouvez tester l’un de ceux qui utilisent l’opérateur typeof qui devrait donner le même résultat: "function".

Maintenant, si vous assignez une chaîne à la propriété "onsubmit" via JavaScript, elle restera une chaîne, donc non appelable. Notez que si vous appliquez l'opérateur typeof à celui-ci, vous obtiendrez "string" au lieu de "function".

J'espère que cela pourrait clarifier quelques points. Là encore, si vous voulez savoir si une telle propriété (ou un identifiant pour le sujet) est une fonction et appelable, l’opérateur typeof devrait faire l'affaire. Bien que je ne sois pas sûr que cela fonctionne correctement sur plusieurs images.

À votre santé

12
Pablo Cabrera

Quel navigateur utilisez-vous?

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

Cela me donne "function" dans IE7 et FireFox.

5
Greg

Assurez-vous que vous appelez typeof sur la fonction réelle, pas un littéral de chaîne:

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

typeof "x"; // returns "string"

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

Vous pouvez essayer de modifier cette technique selon vos besoins:

 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

en utilisant une variable basée sur une chaîne comme exemple et en utilisant instanceof Function Vous enregistrez la fonction..affectez la variable ... vérifiez que la variable est le nom de la fonction ... effectuez un pré-traitement ... affectez la fonction à une nouvelle var ... puis appelez la fonction.

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 sera toujours une fonction définie en tant qu'attribut HTML de l'élément de formulaire. C'est une sorte de fonction anonyme attachée à un élément HTML, qui a le ce pointeur lié à cet élément FORM et également un paramètre nommé event qui contiendra des données sur l’événement submit.

Dans ces circonstances, je ne comprends pas comment vous avez obtenu une chaîne à la suite d'une opération typeof. Vous devriez donner plus de détails, un peu de code.

Edit (en réponse à votre deuxième édition):

Je crois que le gestionnaire attaché à l'attribut HTML s'exécutera indépendamment du code ci-dessus. De plus, vous pouvez essayer de l’arrêter d’une manière ou d’une autre, mais il semble que FF 3, IE 8, Chrome 2 et Opera 9 exécutent le gestionnaire d'attributs HTML en premier lieu, puis celui qui est attaché (je n'ai pas encore testé avec jQuery, mais avec addEventListener et attachEvent). Alors ... que voulez-vous accomplir exactement?

En passant, votre code ne fonctionne pas car votre expression régulière extraira la chaîne "valid ();", qui n'est certainement pas une fonction.

2
Ionuț G. Stan

Si c'est une chaîne, vous pouvez supposer/espérer que c'est toujours de la forme

return SomeFunction(arguments);

analyser le nom de la fonction, puis voir si cette fonction est définie à l'aide de

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

Je pense que la source de confusion est la distinction entre un noeud attribut et le propriété correspondant.

Vous utilisez:

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

Vous lisez directement la valeur de onsubmit attribut (qui doit est une chaîne). Au lieu de cela, vous devriez accéder à la onsubmit propriété du noeud:

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

Voici un test rapide:

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

Cela donne:

 formulaire1 propriété onsubmit: (fonction) fonction onsubmit (événement) {return valid (); } 
 form1 onsubmit attribut: (string) return valid () 
1
Ates Goral

Eh bien, "return valid();"est une chaîne, donc c'est correct.

Si vous voulez vérifier si une fonction est attachée à la place, vous pouvez essayer ceci:

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

Vous pouvez toujours utiliser l'une des fonctions typeOf sur les blogs JavaScript tels que Chris West's . L'utilisation d'une définition telle que celle qui suit pour la fonction typeOf() fonctionnerait:

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

Cette fonction (qui est déclarée dans l'espace de noms global, peut être utilisée comme ceci:

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

S'il s'agit d'une fonction, "Fonction" sera renvoyé. S'il s'agit d'une chaîne, "String" sera renvoyé. D'autres valeurs possibles sont affichées ici .

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