Verifica se il valore è una funzione


88

Devo verificare se il valore di un modulo onsubmitè una funzione. Il formato è tipicamente onsubmit="return valid();". C'è un modo per sapere se questa è una funzione e se è richiamabile? L'uso di typeof restituisce semplicemente che è una stringa, il che non mi aiuta molto.

EDIT : Naturalmente, capisco che "return valid ();" è una stringa. L'ho replaceridotto a "valid ();" e persino a "valid ()". Voglio sapere se una di queste è una funzione.

EDIT : ecco un po 'di codice, che può aiutare a spiegare il mio problema:

$("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 : ecco il nuovo codice. Sembra che devo ancora usare un eval, perché la chiamata a form.submit () non attiva gli onsubmits esistenti.

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

Suggerimenti su come farlo meglio?

Risposte:


85

Sto sostituendo un pulsante di invio con un collegamento di ancoraggio. Poiché la chiamata di form.submit () non attiva onsubmit, lo trovo e lo eval () da solo. Ma vorrei controllare se la funzione esiste prima di eval () ing cosa c'è. - 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: parametro mancante f nella funzione testOnsubmitAndSubmit

Quanto sopra dovrebbe funzionare indipendentemente dal fatto che si assegni l' onsubmitattributo HTML o lo si assegni in JavaScript:

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

1
da dove viene f in f.onsubmit?
Art

fè un'istanza di modulo. Lo passi alla funzione testOnsubmitAndSubmit come argomento. (So ​​che questa domanda è piuttosto vecchia, ma forse la mia risposta farà risparmiare tempo a qualcuno :))
zeroos

63

Provare

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

7
questo è solo un campione. Puoi cambiarlo in button.onsubmit instanceof Function
artemb

13

Puoi semplicemente usare l' typeofoperatore insieme a un operatore ternario in breve:

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

Se è una funzione, la chiamiamo e restituiamo il suo valore di ritorno, altrimenti semplicemente return true

Modificare:

Non sono abbastanza sicuro di quello che vuoi veramente fare, ma cercherò di spiegare cosa potrebbe succedere.

Quando dichiari il tuo onsubmitcodice all'interno del tuo html, questo viene trasformato in una funzione e quindi è richiamabile dal "mondo" JavaScript. Ciò significa che questi due metodi sono equivalenti:

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

Queste due saranno entrambe funzioni ed entrambe saranno richiamabili. È possibile verificare qualsiasi di coloro che usano l' typeofoperatore che dovrebbe resa lo stesso risultato: "function".

Ora se assegni una stringa alla proprietà "onsubmit" tramite JavaScript, rimarrà una stringa, quindi non richiamabile. Nota che se applichi l' typeofoperatore contro di esso, otterrai "string"invece di "function".

Spero che questo possa chiarire alcune cose. Poi di nuovo, se vuoi sapere se tale proprietà (o qualsiasi identificatore per la questione) è una funzione e richiamabile, l' typeofoperatore dovrebbe fare il trucco. Anche se non sono sicuro che funzioni correttamente su più frame.

Saluti


Tuttavia, ho bisogno di testarlo al di fuori di onsubmit.
Glen Solsberry,

5

Quale browser utilizzate?

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

Questo mi dà " function" in IE7 e FireFox.


Anche se il tuo onsubmit è "return valid ();"?
Glen Solsberry,

1
Sì, non dimenticare che non puoi avere "return" al di fuori di una funzione.
Greg

form.onsubmit sarà sempre una funzione fintanto che è definita come attributo HTML. Vedi la mia risposta.
Ionuț G. Stan,

4

usando una variabile basata su stringa come esempio e facendo uso instanceof Function Registri la funzione..assegna la variabile ... controlla che la variabile sia il nome della funzione ... fai pre-process ... assegna la funzione a nuova var ... poi chiama la funzione.

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
Non hai davvero bisogno di quella variabile fn, potresti semplicemente usare window [value] ();
Lajos Meszaros

1
sì, lo so ma mi rendo anche conto che generalmente è più facile da capire in un formato lungo e poiché questo è principalmente un sito per imparare il tuo contributo è comunque apprezzato @LajosMeszaros
CrandellWS

3

Assicurati di chiamare typeof sulla funzione effettiva, non una stringa letterale:

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

typeof "x"; // returns "string"

typeof x; // returns "function"

3

Puoi provare a modificare questa tecnica in base alle tue esigenze:

 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 sarà sempre una funzione quando definito come un attributo dell'HTML dell'elemento form. È una sorta di funzione anonima collegata a un elemento HTML, che ha il puntatore this associato a quell'elemento FORM e ha anche un parametro denominato eventche conterrà i dati sull'evento di invio.

In queste circostanze non capisco come hai ottenuto una stringa come risultato di un tipo di operazione. Dovresti fornire maggiori dettagli, meglio un po 'di codice.

Modifica (in risposta alla tua seconda modifica):

Credo che il gestore collegato all'attributo HTML verrà eseguito indipendentemente dal codice sopra. Inoltre, potresti provare a fermarlo in qualche modo, ma, sembra che FF 3, IE 8, Chrome 2 e Opera 9 stiano eseguendo il gestore degli attributi HTML in primo luogo e poi quello allegato (non ho testato con jQuery sebbene, ma con addEventListener e attachEvent). Allora ... cosa stai cercando di ottenere esattamente?

A proposito, il tuo codice non funziona perché la tua espressione regolare estrarrà la stringa "valid ();", che sicuramente non è una funzione.


2

Se è una stringa, potresti presumere / sperare che sia sempre della forma

return SomeFunction(arguments);

analizzare il nome della funzione e quindi vedere se tale funzione è definita utilizzando

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

stavo per aggiungere anche questa risoluzione ... ricordati di registrare la funzione a livello di documento / finestra
CrandellWS

1

Beh, "return valid();" è una stringa, in modo che è corretto.

Se invece vuoi controllare se ha una funzione allegata, puoi provare questo:

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

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

1

Penso che la fonte di confusione sia la distinzione tra l' attributo di un nodo e la proprietà corrispondente .

Stai usando:

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

Stai leggendo direttamente il valore onsubmit dell'attributo (che deve essere una stringa). Invece, dovresti accedere alla onsubmit proprietà del nodo:

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

Ecco un rapido 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> 

Questo produce:

form1 proprietà onsubmit: (funzione) funzione onsubmit (evento) {return valid (); }
attributo form1 onsubmit: (stringa) return valid ()

1
  if ( window.onsubmit ) {
     //
  } else {
     alert("Function does not exist.");
  }

1

Non è typeof xxx === 'function'il migliore e il più veloce?

Ho realizzato una panchina in cui puoi provarlo, rispetto a instanceof e _underscore

  1. Sembra che sia più veloce di instanceof (usando chrome)
  2. Non creerà un errore se la variabile non è definita

Ecco una panchina: https://jsbench.me/qnkf076cqb/1


0

Puoi sempre utilizzare una delle funzioni typeOf sui blog JavaScript come quello di Chris West . L'utilizzo di una definizione come la seguente per la typeOf()funzione funzionerebbe:

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

Questa funzione (che è dichiarata nello spazio dei nomi globale, può essere utilizzata in questo modo:

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

Se si tratta di una funzione, verrà restituita "Funzione". Se è una stringa, verrà restituito "String". Altri possibili valori sono mostrati qui .


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

Un semplice controllo come questo ti farà sapere se esiste / definito:

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

6
Questo non funzionerà. If asserirà come TRUE quando onsubmit è anche una stringa non vuota.
Seb

1
Un modo orribile di verificare se qualcosa è una funzione - come indicato, e per essere più chiari: qualsiasi cosa "veritiera" farebbe sì che questo codice "facesse qualcosa" e questo potrebbe non essere ciò che ci si aspetta. Se this.onsubmit fosse impostato sul valore 5 o "hello" o qualsiasi altra cosa in JavaScript che restituisce true, si verificherà un comportamento imprevisto.
Jason Bunting,

L'oggetto della domanda chiede come verificare se qualcosa esiste. Questo è tutto quello che stavo suggerendo - né più né meno.
Kon

Non proprio - l'originale pubblicato afferma che ha la "necessità di verificare se il valore di onsubmit di un modulo è una funzione". La tua condizione non è se this.onsubmit sia o meno una funzione, il tuo test chiede semplicemente se this.onsubmit è "veritiero" o meno
Jason Bunting,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.