เมื่อตัดสินประเภทฟังก์ชัน เรามักจะใช้วิธี typeof ภายใต้สถานการณ์ปกติ ก็จะได้ผลลัพธ์ตามที่เราคาดหวัง อย่างไรก็ตามยังมีรายละเอียดบางอย่างที่เรายังไม่ทราบดีนัก หลังจากวิเคราะห์รายละเอียดเหล่านี้แล้ว John Resig ได้ให้วิธีแก้ปัญหาที่สมบูรณ์แบบแก่เรา ซึ่งจะแนะนำโดยละเอียดในบทความนี้:
1.ไม่ทราบรายละเอียดวิธีการแบบเดิมๆ
ไม่ต้องสงสัยเลยว่าเมื่อพิจารณาประเภทฟังก์ชัน เราจะใช้วิธี typeof เช่น:
ฟังก์ชั่น fn(){
//เนื้อหา
-
alert(typeof fn)//ผลลัพธ์คือ "function"
อย่างไรก็ตาม วิธีการนี้ใช้ไม่ได้ตามที่คาดไว้ในบางเบราว์เซอร์
1. ไฟร์ฟอกซ์2 และไฟร์ฟอกซ์3
ในเบราว์เซอร์ทั้งสองนี้ การใช้ typeof เพื่อตรวจจับประเภทขององค์ประกอบออบเจ็กต์ HTML ส่งผลให้เกิดผลลัพธ์ "ฟังก์ชัน" ที่ไม่แม่นยำแทนที่จะเป็น "ออบเจ็กต์" เช่น HTMLDocument ชอบ:
การแจ้งเตือน (ประเภทของ HTMLDocument);
//ใน Firefox2 ผลลัพธ์คือ "function";
//ใน Firefox3 ผลลัพธ์คือ "object";
2. ไฟร์ฟอกซ์2
สำหรับนิพจน์ทั่วไป ผลลัพธ์ที่ส่งคืนในเบราว์เซอร์นี้คือ "function" (ผลลัพธ์คือ "object" ใน Firefox3) เช่น:
var reg = /ทดสอบ/;
การแจ้งเตือน (ประเภทของ reg);
//ใน Firefox2 ผลลัพธ์คือ "function";
//ใน Firefox3 ผลลัพธ์คือ "object";
หมายเหตุ: ฉันทดสอบใน Safari และผลลัพธ์ก็คือ "ฟังก์ชั่น" เช่นกัน
3. IE6 และ IE7
เมื่อใช้วิธีการ typeof ในองค์ประกอบ DOM ใน IE ผลลัพธ์คือ "วัตถุ" ชอบ:
alert(typeof document.getElementsByTagName("body")[0].getAttribute);
//ผลลัพธ์ที่ได้คือ "วัตถุ"
4. ซาฟารี 3
Safari คิดว่าองค์ประกอบ NodeList ของ DOM เป็นฟังก์ชัน เช่น:
การแจ้งเตือน (ประเภทของ document.body.childNodes);
//ผลลัพธ์ที่ได้คือ "ฟังก์ชั่น"
แน่นอนว่า หากคุณต้องการทดสอบว่าวัตถุนั้นเป็นฟังก์ชันหรือไม่ การใช้เมธอด typeof ไม่ได้รับประกันผลการทดสอบตามความเป็นจริง จากนั้น เราต้องการโซลูชันที่รับประกันผลการทดสอบในเบราว์เซอร์ทั้งหมด เรารู้ว่าฟังก์ชันมีสองวิธีคือ Apply() และ Call() แต่ทั้งสองวิธีนี้ไม่มีอยู่ในฟังก์ชันที่มีปัญหาใน IE ลองทดสอบต่อไปนี้:
alert(typeof document.getElementsByTagName("body")[0].getAttribute.call)
//ผลลัพธ์คือ "ไม่ได้กำหนด" ใน IE
แน่นอนว่าเราไม่สามารถใช้ประโยชน์จากทั้งสองวิธีนี้ได้
2. โซลูชั่นและกระบวนการดำเนินการที่สมบูรณ์แบบ
John Resig ให้วิธีแก้ปัญหาที่สมบูรณ์แบบแก่เรา วิธีการที่ซับซ้อนแต่มีเสถียรภาพในการพิจารณาว่าวัตถุเป็นฟังก์ชันมีดังนี้:
ฟังก์ชั่น isFunction( fn ) {
กลับ !!fn && !fn.nodeName && fn.constructor != สตริง &&
fn.constructor != RegExp && fn.constructor != อาร์เรย์ &&
/function/i.test( fn + "" );
-
ขั้นแรกฟังก์ชันนี้จะทำให้แน่ใจได้ว่าวัตถุทดสอบมีอยู่และทำให้เป็นอนุกรมในสตริงที่มี "function" นี่คือพื้นฐานของการตรวจจับของเรา (fn.constructor != String, fn.constructor != Array และ fn.constructor != RegExp ) . นอกจากนี้ เราต้องแน่ใจว่าฟังก์ชันที่ประกาศไม่ใช่โหนด DOM (fn.nodeName) จากนั้นเราสามารถทำการทดสอบ toString ได้ หากเราแปลงฟังก์ชันเป็นสตริง ในเบราว์เซอร์ (fn+"") จะให้ผลลัพธ์เช่นนี้ "ชื่อฟังก์ชัน(){...}" ในตอนนี้ การพิจารณาว่ามันเป็นฟังก์ชันนั้นทำได้ง่ายเพียงแค่ตรวจสอบว่าสตริงมีคำว่า "function" หรือไม่ สิ่งนี้ได้ผลอย่างมหัศจรรย์ สำหรับฟังก์ชันใดๆ ก็ตามที่เป็นปัญหา เราได้ผลลัพธ์ที่เราต้องการในทุกเบราว์เซอร์ เมื่อเปรียบเทียบกับวิธีการแบบเดิม ความเร็วการทำงานของฟังก์ชันนี้ค่อนข้างไม่น่าพอใจ ผู้เขียนแนะนำให้ใช้อย่างระมัดระวัง
John Resig เป็นผู้พัฒนาไลบรารี jQuery ฉันเชื่อว่าเพื่อน ๆ ที่ใช้ไลบรารีนี้คุ้นเคยกับไวยากรณ์ที่กระชับและประสิทธิภาพที่ยอดเยี่ยม นอกเหนือจากการแสวงหาความเรียบง่ายของโค้ดและประสิทธิภาพสูงแล้ว จิตวิญญาณแห่งความสมบูรณ์แบบของผู้เขียนยังน่าประทับใจอีกด้วย หากคุณเป็นคนชอบความสมบูรณ์แบบ ฉันเชื่อว่าบทความนี้จะเป็นประโยชน์กับคุณ
ข้อความต้นฉบับ: http://www.denisdeng.com/?p=426