Menguji apakah nilai adalah suatu fungsi

88

Saya perlu menguji apakah nilai formulir onsubmitadalah fungsi. Formatnya biasanya onsubmit="return valid();". Apakah ada cara untuk mengetahui apakah ini suatu fungsi, dan apakah dapat dipanggil? Menggunakan typeof hanya mengembalikan bahwa itu adalah string, yang tidak banyak membantu saya.

EDIT : Tentu saja, saya mengerti bahwa "return valid ();" adalah sebuah string. Saya telah replacemelakukannya ke "valid ();", dan bahkan "valid ()". Saya ingin tahu apakah salah satu dari itu adalah fungsi.

EDIT : Berikut beberapa kode, yang dapat membantu menjelaskan masalah saya:

$("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 : Ini kode baru. Sepertinya saya masih harus menggunakan eval, karena memanggil form.submit () tidak mengaktifkan onsubmits yang ada.

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

Saran tentang bagaimana melakukan ini dengan lebih baik?

Glen Solsberry
sumber

Jawaban:

85

Saya mengganti tombol kirim dengan tautan jangkar. Karena memanggil form.submit () tidak mengaktifkan onsubmit, saya menemukannya, dan mengevaluasi sendiri. Tapi saya ingin memeriksa apakah fungsinya ada sebelum hanya mengevaluasi apa yang ada. - 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: parameter f hilang dalam function testOnsubmitAndSubmit

Hal di atas harus berfungsi terlepas dari apakah Anda menetapkan onsubmitatribut HTML atau menetapkannya di JavaScript:

document.forms['theForm'].onsubmit = onsubmitHandler;
Berikan Wagner
sumber
1
darimana f di f.onsubmit berasal?
Seni
fadalah contoh formulir. Anda meneruskannya ke fungsi testOnsubmitAndSubmit sebagai argumen. (Saya tahu pertanyaan ini cukup lama, tetapi mungkin jawaban saya akan menghemat waktu seseorang :))
zeroos
63

Mencoba

if (this.onsubmit instanceof Function) {
    // do stuff;
}
artemb
sumber
7
itu hanya contoh. Anda dapat mengubahnya menjadi button.onsubmit instanceof Function
artemb
13

Anda cukup menggunakan typeofoperator bersama dengan operator terner singkatnya:

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

Jika itu adalah fungsi yang kita panggil dan kembalikan nilai kembaliannya, jika tidak kembalikan saja true

Edit:

Saya tidak begitu yakin apa yang sebenarnya ingin Anda lakukan, tetapi saya akan mencoba menjelaskan apa yang mungkin terjadi.

Ketika Anda mendeklarasikan onsubmitkode Anda dalam html Anda, itu akan berubah menjadi fungsi dan dengan demikian dapat dipanggil dari "dunia" JavaScript. Artinya, kedua metode itu setara:

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

Keduanya akan menjadi fungsi dan keduanya dapat dipanggil. Anda dapat menguji salah satu dari mereka menggunakan typeofoperator yang yang harus yeld hasil yang sama: "function".

Sekarang jika Anda menetapkan string ke properti "onsubmit" melalui JavaScript, itu akan tetap menjadi string, karenanya tidak dapat dipanggil. Perhatikan bahwa jika Anda menerapkan typeofoperator terhadapnya, Anda akan mendapatkan "string"alih-alih "function".

Saya harap ini dapat menjelaskan beberapa hal. Kemudian lagi, jika Anda ingin mengetahui apakah properti tersebut (atau pengenal apa pun untuk masalah ini) adalah sebuah fungsi dan dapat dipanggil, typeofoperator harus melakukan triknya. Meskipun saya tidak yakin apakah itu berfungsi dengan baik di banyak bingkai.

Bersulang

Pablo Cabrera
sumber
Saya perlu menguji ini di luar onsubmit.
Glen Solsberry
5

Browser apa yang Anda gunakan?

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

Ini memberi saya " function" di IE7 dan FireFox.

Greg
sumber
Meskipun pengiriman Anda adalah "return valid ();"?
Glen Solsberry
1
Ya - jangan lupa, Anda tidak bisa memiliki "return" di luar fungsi.
Greg
form.onsubmit akan selalu menjadi fungsi selama itu didefinisikan sebagai atribut HTML. Lihat jawabanku.
Ionuț G. Stan
4

menggunakan variabel berbasis string sebagai contoh dan memanfaatkan instanceof Function Anda mendaftarkan fungsi .. menetapkan variabel ... memeriksa variabel adalah nama fungsi ... melakukan pra-proses ... menetapkan fungsi ke var baru ... lalu panggil fungsinya.

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
sumber
2
Anda tidak benar-benar membutuhkan variabel fn itu, Anda bisa menggunakan window [value] ();
Lajos Meszaros
1
ya, saya tahu, tetapi saya juga menyadari bahwa umumnya lebih mudah untuk dipahami dalam format panjang dan karena ini pada dasarnya adalah situs untuk mempelajari masukan Anda dihargai dalam hal apa pun @LajosMeszaros
CrandellWS
3

Pastikan Anda memanggil typeof pada fungsi sebenarnya, bukan string literal:

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

typeof "x"; // returns "string"

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

Anda dapat mencoba memodifikasi teknik ini agar sesuai dengan kebutuhan Anda:

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

form.onsubmit akan selalu menjadi fungsi ketika didefinisikan sebagai atribut HTML elemen formulir. Ini semacam fungsi anonim yang dilampirkan ke elemen HTML, yang memiliki penunjuk ini terikat ke elemen FORM tersebut dan juga memiliki parameter bernama eventyang akan berisi data tentang peristiwa pengiriman.

Dalam keadaan ini, saya tidak mengerti bagaimana Anda mendapatkan string sebagai hasil dari operasi jenis. Anda harus memberikan lebih banyak detail, lebih baik beberapa kode.

Edit (sebagai tanggapan atas suntingan kedua Anda):

Saya yakin penangan yang dilampirkan ke atribut HTML akan dijalankan terlepas dari kode di atas. Lebih jauh lagi, Anda dapat mencoba menghentikannya entah bagaimana, tetapi, tampaknya FF 3, IE 8, Chrome 2 dan Opera 9 menjalankan penangan atribut HTML di tempat pertama dan kemudian yang terpasang (saya tidak menguji dengan jQuery meskipun, tetapi dengan addEventListener dan attachEvent). Jadi ... sebenarnya apa yang ingin kamu capai?

Ngomong-ngomong, kode Anda tidak berfungsi karena ekspresi reguler Anda akan mengekstrak string "valid ();", yang jelas bukan fungsi.

Ionuț G. Stan
sumber
2

Jika itu sebuah string, Anda bisa berasumsi / berharap itu selalu dalam bentuknya

return SomeFunction(arguments);

parse untuk nama fungsi, lalu lihat apakah fungsi itu ditentukan menggunakan

if (window[functionName]) { 
    // do stuff
}
millimoose.dll
sumber
saya akan menambahkan resolusi ini juga ... ingatlah untuk mendaftarkan fungsi di tingkat dokumen / jendela
CrandellWS
1

Ini "return valid();" adalah string, jadi itu benar.

Jika Anda ingin memeriksa apakah itu memiliki fungsi yang dilampirkan, Anda dapat mencoba ini:

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

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

Menurut saya sumber kebingungan adalah perbedaan antara atribut node dan properti terkait .

Anda menggunakan:

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

Anda langsung membaca nilai onsubmit atribut (yang harus berupa string). Sebagai gantinya, Anda harus mengakses onsubmit properti node:

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

Berikut tes singkatnya:

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

Ini menghasilkan:

properti onsubmit form1: (function) function onsubmit (event) {return valid (); }
atribut onsubmit form1: (string) return valid ()
Ates Goral
sumber
1
  if ( window.onsubmit ) {
     //
  } else {
     alert("Function does not exist.");
  }
TStamper
sumber
1

Bukankah typeof xxx === 'function'yang terbaik dan tercepat?

Saya membuat bangku di mana Anda dapat mencobanya, dibandingkan dengan instanceof dan _underscore

  1. Sepertinya lebih cepat daripada instanceof (menggunakan chrome)
  2. Ini tidak akan memunculkan kesalahan jika variabel tidak ditentukan

Berikut bangku: https://jsbench.me/qnkf076cqb/1


sumber
0

Anda selalu dapat menggunakan salah satu fungsi typeOf di blog JavaScript seperti milik Chris West . Menggunakan definisi seperti berikut untuk typeOf()fungsi tersebut akan berhasil:

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

Fungsi ini (yang dideklarasikan di namespace global, bisa digunakan seperti ini:

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

Jika itu adalah sebuah fungsi, "Fungsi" akan dikembalikan. Jika itu adalah string, "String" akan dikembalikan. Nilai-nilai lain yang mungkin ditampilkan di sini .

Xavier Botomon
sumber
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
sumber
-3

Pemeriksaan sederhana seperti ini akan memberi tahu Anda jika ada / ditentukan:

if (this.onsubmit)
{
  // do stuff;
}
Kon
sumber
6
Ini tidak akan berhasil. If will assert to TRUE ketika onsubmit juga merupakan string yang tidak kosong.
Seb
1
Cara yang mengerikan untuk menguji apakah sesuatu adalah sebuah fungsi - seperti yang ditunjukkan, dan untuk lebih jelasnya: apa pun yang "benar" akan menyebabkan kode ini "melakukan sesuatu" dan itu mungkin tidak seperti yang diharapkan. Jika this.onsubmit disetel ke nilai 5 atau "hello" atau apa pun di JavaScript yang mengevaluasi true, Anda akan mendapatkan perilaku yang tidak terduga.
Jason Bunting
Subjek pertanyaan menanyakan bagaimana cara memeriksa apakah ada sesuatu. Itu saja yang saya sarankan - tidak lebih, tidak kurang.
Kon
Tidak juga - postingan asli menyatakan bahwa ia memiliki "kebutuhan untuk menguji apakah nilai pengiriman formulir adalah sebuah fungsi." Kondisi Anda bukanlah apakah this.onsubmit adalah sebuah fungsi atau tidak, pengujian Anda akan menanyakan apakah this.onsubmit adalah "benar" atau tidak
Jason Bunting