การทดสอบว่าค่าเป็นฟังก์ชันหรือไม่


89

ฉันต้องการทดสอบว่าค่าของฟอร์มonsubmitเป็นฟังก์ชันหรือไม่ onsubmit="return valid();"รูปแบบที่เป็นปกติ มีวิธีที่จะบอกได้หรือไม่ว่านี่คือฟังก์ชันและสามารถเรียกใช้ได้หรือไม่? การใช้ typeof เพียงแค่ส่งกลับว่าเป็นสตริงซึ่งไม่ได้ช่วยอะไรฉันมากนัก

แก้ไข : แน่นอนฉันเข้าใจว่า "return valid ();" เป็นสตริง ฉันได้replaceลงไปเป็น "valid ();" และแม้แต่ "valid ()" ฉันต้องการทราบว่าสิ่งเหล่านี้เป็นฟังก์ชันหรือไม่

แก้ไข : นี่คือรหัสบางส่วนซึ่งอาจช่วยอธิบายปัญหาของฉัน:

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

แก้ไข 2 : นี่คือรหัสใหม่ ดูเหมือนว่าฉันยังต้องใช้ eval เนื่องจากการเรียก form.submit () ไม่เริ่มการส่งข้อมูลที่มีอยู่

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

ข้อเสนอแนะเกี่ยวกับวิธีการทำสิ่งนี้ให้ดีขึ้นหรือไม่?

คำตอบ:


86

ฉันกำลังแทนที่ปุ่มส่งด้วยสมอลิงค์ เนื่องจากการเรียก form.submit () ไม่เปิดใช้งาน onsubmit ฉันจึงค้นหามันและประเมิน () ด้วยตัวเอง แต่ฉันต้องการตรวจสอบว่ามีฟังก์ชั่นนี้อยู่หรือไม่ก่อนที่จะทำการประเมิน () ว่ามีอะไรอยู่ - 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>

แก้ไข: ไม่มีพารามิเตอร์ f ในฟังก์ชัน testOnsubmitAndSubmit

ข้างต้นควรใช้งานได้ไม่ว่าคุณจะกำหนดonsubmitแอตทริบิวต์ HTML หรือกำหนดใน JavaScript:

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

1
f ใน f.onsubmit มาจากไหน?
ศิลปะ

fเป็นอินสแตนซ์แบบฟอร์ม คุณส่งผ่านไปยังฟังก์ชัน testOnsubmitAndSubmit เป็นอาร์กิวเมนต์ (ฉันรู้ว่าคำถามนี้ค่อนข้างเก่า แต่คำตอบของฉันอาจจะช่วยใครบางคนได้บ้าง :))
zeroos

64

ลอง

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

7
นั่นเป็นเพียงตัวอย่าง คุณสามารถเปลี่ยนเป็นปุ่มส่งอินสแตนซ์ของฟังก์ชัน
artemb

13

คุณสามารถใช้typeofโอเปอเรเตอร์ร่วมกับโอเปอเรเตอร์ด้านท้ายสั้น ๆ :

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

ถ้ามันเป็นฟังก์ชันที่เราเรียกมันและส่งคืนค่าที่ส่งคืนมิฉะนั้นจะกลับมา true

แก้ไข:

ฉันไม่ค่อยแน่ใจว่าคุณต้องการทำอะไรจริงๆ แต่ฉันจะพยายามอธิบายสิ่งที่อาจเกิดขึ้น

เมื่อคุณประกาศonsubmitรหัสของคุณภายใน html ของคุณโค้ดจะกลายเป็นฟังก์ชันและสามารถเรียกใช้งานได้จาก "โลก" ของ JavaScript นั่นหมายความว่าสองวิธีนี้เทียบเท่ากัน:

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

ทั้งสองจะเป็นทั้งสองฟังก์ชันและทั้งสองจะสามารถเรียกใช้ได้ คุณสามารถทดสอบใด ๆ ของผู้ใช้typeofผู้ประกอบการซึ่งควร yeld "function"ผลเดียวกัน:

ตอนนี้ถ้าคุณกำหนดสตริงให้กับคุณสมบัติ "onsubmit" ผ่านทาง JavaScript สตริงนั้นจะยังคงเป็นสตริงดังนั้นจึงไม่สามารถเรียกได้ ขอให้สังเกตว่าถ้าคุณใช้typeofประกอบกับมันคุณจะได้รับแทน"string""function"

ฉันหวังว่านี่อาจจะชี้แจงบางสิ่งได้ จากนั้นอีกครั้งหากคุณต้องการทราบว่าคุณสมบัติดังกล่าว (หรือตัวระบุใด ๆ สำหรับกรณี) เป็นฟังก์ชันและสามารถเรียกใช้ได้typeofผู้ประกอบการควรดำเนินการ แม้ว่าฉันจะไม่แน่ใจว่ามันทำงานได้ดีในหลาย ๆ เฟรมหรือไม่

ไชโย


ฉันจำเป็นต้องทดสอบสิ่งนี้นอกเหนือจาก onsubmit
Glen Solsberry

5

สิ่งที่เบราว์เซอร์ที่คุณใช้?

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

สิ่งนี้ทำให้ฉันมี " function" ใน IE7 และ FireFox


แม้ว่า onsubmit ของคุณจะเป็น "return valid ();"?
Glen Solsberry

1
ใช่ - อย่าลืมว่าคุณไม่สามารถมี "return" นอกฟังก์ชันได้
Greg

form.onsubmit จะเป็นฟังก์ชันเสมอตราบเท่าที่กำหนดเป็นแอตทริบิวต์ HTML ดูคำตอบของฉัน
Ionuț G. Stan

4

โดยใช้ตัวแปรตามสตริงเป็นตัวอย่างและการใช้งาน 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();
}

2
คุณไม่ต้องการตัวแปร fn จริงๆคุณสามารถใช้ window [value] ();
Lajos Meszaros

1
ใช่ฉันรู้ แต่ฉันก็ตระหนักดีว่าโดยทั่วไปแล้วมันง่ายกว่าที่จะเข้าใจในรูปแบบยาวและเนื่องจากนี่เป็นเว็บไซต์สำหรับการเรียนรู้ข้อมูลที่คุณป้อนจึงมีมูลค่าไม่ว่าในกรณีใด ๆ @LajosMeszaros
CrandellWS

3

ตรวจสอบให้แน่ใจว่าคุณกำลังเรียก typeof บนฟังก์ชันจริงไม่ใช่สตริงลิเทอรัล:

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

typeof "x"; // returns "string"

typeof x; // returns "function"

3

คุณสามารถลองปรับเปลี่ยนเทคนิคนี้ให้เหมาะกับความต้องการของคุณ:

 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 จะเป็นฟังก์ชันเสมอเมื่อกำหนดเป็นแอตทริบิวต์ของ HTML องค์ประกอบฟอร์ม เป็นฟังก์ชันที่ไม่ระบุชื่อบางประเภทที่แนบมากับองค์ประกอบ HTML ซึ่งมีตัวชี้นี้เชื่อมโยงกับองค์ประกอบ FORM นั้นและยังมีพารามิเตอร์ที่ตั้งชื่อeventซึ่งจะมีข้อมูลเกี่ยวกับเหตุการณ์ที่ส่ง

ภายใต้สถานการณ์เหล่านี้ฉันไม่เข้าใจว่าคุณมีสตริงอันเป็นผลมาจากการดำเนินการ typeof ได้อย่างไร คุณควรให้รายละเอียดเพิ่มเติมดีกว่าบางรหัส

แก้ไข (เป็นการตอบสนองต่อการแก้ไขครั้งที่สองของคุณ):

ฉันเชื่อว่าตัวจัดการที่แนบมากับแอตทริบิวต์ HTML จะดำเนินการโดยไม่คำนึงถึงรหัสข้างต้น ยิ่งไปกว่านั้นคุณสามารถลองหยุดมันได้ แต่ดูเหมือนว่า FF 3, IE 8, Chrome 2 และ Opera 9 กำลังเรียกใช้ตัวจัดการแอตทริบิวต์ HTML ในตอนแรกจากนั้นจึงแนบมา (ฉันไม่ได้ทดสอบกับ jQuery แม้ว่า แต่ด้วย addEventListener และ attachEvent) แล้ว ... คุณพยายามทำอะไรให้สำเร็จ?

อย่างไรก็ตามรหัสของคุณไม่ทำงานเนื่องจากนิพจน์ทั่วไปของคุณจะดึงสตริง "valid ();" ซึ่งไม่ใช่ฟังก์ชันอย่างแน่นอน


2

หากเป็นสตริงคุณสามารถสมมติ / หวังว่ามันจะอยู่ในรูปแบบเสมอ

return SomeFunction(arguments);

แยกวิเคราะห์ชื่อฟังก์ชันจากนั้นดูว่าฟังก์ชันนั้นถูกกำหนดโดยใช้หรือไม่

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

ฉันกำลังจะเพิ่มความละเอียดนี้เช่นกัน ... อย่าลืมลงทะเบียนฟังก์ชันที่ระดับเอกสาร / หน้าต่าง
CrandellWS

1

ดี"return valid();" เป็นสตริงเพื่อให้ถูกต้อง

หากคุณต้องการตรวจสอบว่ามีฟังก์ชันที่แนบมาแทนหรือไม่คุณสามารถลองสิ่งนี้:

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

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

1

ฉันคิดว่าที่มาของความสับสนคือความแตกต่างระหว่างแอตทริบิวต์ของโหนดและคุณสมบัติที่เกี่ยวข้อง

คุณกำลังใช้:

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

คุณกำลังอ่านค่าonsubmit แอตทริบิวต์โดยตรง(ซึ่งต้องเป็นสตริง) คุณควรเข้าถึงonsubmit คุณสมบัติของโหนดแทน:

$("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 property: (function) function onsubmit (event) {return valid (); }
form1 onsubmit แอตทริบิวต์: (string) return valid ()


1

ไม่typeof xxx === 'function'ดีที่สุดและเร็วที่สุด?

ฉันสร้างม้านั่งซึ่งคุณสามารถลองเทียบกับ instanceof และ _underscore

  1. ดูเหมือนว่าจะเร็วกว่า instanceof (ใช้ chrome)
  2. จะไม่เกิดข้อผิดพลาดหากไม่ได้กำหนดตัวแปร

นี่คือม้านั่ง: https://jsbench.me/qnkf076cqb/1


0

คุณสามารถใช้ฟังก์ชัน typeOf อย่างใดอย่างหนึ่งในบล็อก JavaScript เช่นChris West'sได้ตลอดเวลา การใช้คำจำกัดความดังต่อไปนี้สำหรับtypeOf()ฟังก์ชันจะใช้ได้:

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

ฟังก์ชันนี้ (ซึ่งประกาศในเนมสเปซส่วนกลางสามารถใช้ได้ดังนี้:

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

หากเป็นฟังก์ชัน "ฟังก์ชัน" จะถูกส่งกลับ หากเป็นสตริงระบบจะส่งคืน "สตริง" ค่าที่เป็นไปได้อื่น ๆ จะแสดงที่นี่


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

การตรวจสอบง่ายๆเช่นนี้จะแจ้งให้คุณทราบว่ามีอยู่ / กำหนดไว้หรือไม่:

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

6
วิธีนี้ใช้ไม่ได้ if จะยืนยันเป็น TRUE เมื่อ onsubmit เป็นสตริงที่ไม่ว่างเปล่าเช่นกัน
Seb

1
วิธีทดสอบที่น่าสยดสยองว่าบางสิ่งเป็นฟังก์ชันหรือไม่ตามที่ระบุไว้และเพื่อให้ชัดเจนขึ้น: สิ่งใดก็ตามที่ "จริง" จะทำให้รหัสนี้ "ทำสิ่งต่างๆ" และนั่นอาจไม่ใช่สิ่งที่คาดหวัง ถ้า this.onsubmit ถูกตั้งค่าเป็น 5 หรือ "hello" หรือสิ่งอื่นใดใน JavaScript ที่ประเมินว่าเป็นจริงคุณจะได้รับพฤติกรรมที่ไม่คาดคิด
Jason Bunting

เรื่องของคำถามถามว่าจะตรวจสอบได้อย่างไรว่ามีอะไรอยู่ นั่นคือทั้งหมดที่ฉันแนะนำ - ไม่มากไม่น้อย
คอน

ไม่จริง - ต้นฉบับที่โพสต์ระบุว่าเขามี "ต้องทดสอบว่าค่าของการส่งแบบฟอร์มเป็นฟังก์ชันหรือไม่" เงื่อนไขของคุณไม่ว่านี่หรือไม่ส่งเป็น funciton การทดสอบของคุณเพียงแค่ถามว่าสิ่งนี้ส่งคือ "จริง" หรือไม่
Jason Bunting
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.