ใน JavaScript เรามักจะเห็นรหัสเช่นนี้: การเปรียบเทียบตัวแปรกับ NULL (การใช้งานนี้เป็นปัญหามาก) ใช้เพื่อตรวจสอบว่าตัวแปรได้รับค่าที่สมเหตุสมผลหรือไม่ ตัวอย่างเช่น:
var controller = {กระบวนการ: ฟังก์ชั่น (รายการ) {ถ้า (รายการ! == null) {// วิธีการเขียนที่ไม่ดี items.sort (); items.foreach (ฟังก์ชั่น (รายการ) {// ดำเนินการลอจิก});}}}}ในรหัสนี้วิธีการกระบวนการ () เห็นได้ชัดว่ารายการคาดว่ารายการจะเป็นอาร์เรย์เพราะเราเห็นว่ารายการมีการเรียงลำดับ () และ foreach () ความตั้งใจของรหัสนี้ชัดเจนมาก: หากรายการพารามิเตอร์ไม่ใช่หมายเลขกลุ่มการดำเนินการครั้งต่อไปจะหยุดลง ปัญหาเกี่ยวกับวิธีการเขียนนี้คือการเปรียบเทียบกับ null ไม่สามารถป้องกันข้อผิดพลาดได้ ค่าของรายการสามารถเป็น 1, สตริงหรือแม้แต่วัตถุใด ๆ ค่าเหล่านี้จะไม่เท่ากับ NULL ซึ่งจะทำให้เกิดข้อผิดพลาดเมื่อวิธีกระบวนการ () ถูกดำเนินการเพื่อเรียงลำดับ ()
การเปรียบเทียบกับ NULL เพียงอย่างเดียวนั้นไม่ได้ให้ข้อมูลเพียงพอที่จะตรวจสอบว่าการดำเนินการรหัสที่ตามมานั้นปลอดภัยจริง ๆ หรือไม่ โชคดีที่ JavaScript ให้เราหลายวิธีในการตรวจจับค่าที่แท้จริงของตัวแปร
ตรวจจับค่าดั้งเดิม
มี 5 ประเภทดั้งเดิม (หรือที่เรียกว่าชนิดข้อมูลง่าย ๆ ) ใน JavaScript: String, Number, Boolean, Undefined และ Null หากคุณต้องการให้ค่าเป็นสตริงตัวเลขบูลีนหรือไม่ได้กำหนดตัวเลือกที่ดีที่สุดคือการใช้ตัวดำเนินการ typeof ซึ่งส่งคืนสตริงที่แสดงถึงประเภท
สำหรับสตริง typeof ส่งคืน "สตริง"
สำหรับตัวเลข typeof ส่งคืน "หมายเลข"
สำหรับบูลีน typeof ส่งคืน "บูลีน"
สำหรับ undefined typeof ส่งคืน "undefined"
ไวยากรณ์พื้นฐานของ typeof คือ: ตัวแปร typeof คุณยังสามารถใช้ typeof (ตัวแปร) แม้ว่านี่จะเป็นไวยากรณ์ JavaScript ที่ถูกกฎหมายซึ่งทำให้ Typeof ดูเหมือนฟังก์ชั่นแทนที่จะเป็นตัวดำเนินการ ในมุมมองนี้เราขอแนะนำให้เขียนโดยไม่มีวงเล็บ
การใช้ typeof เพื่อตรวจจับรูปแบบดั้งเดิมทั้ง 4 ประเภทนี้ปลอดภัยมาก มาดูตัวอย่างต่อไปนี้กันเถอะ
// ตรวจพบ "สตริง" ถ้า (typeof name === "string") {oundName = name.substring (3);} // ตรวจจับ "หมายเลข" ถ้า (count typeof === "number") {updateCount (นับ);} // ตรวจจับ "boolean" ถ้า (typeof myapp === "undefined") {myapp = {// รหัสอื่น};}ตัวดำเนินการ typeof นั้นไม่ซ้ำกันซึ่งจะไม่รายงานข้อผิดพลาดเมื่อใช้กับตัวแปรที่ไม่ได้ประกาศ ตัวแปรที่ไม่ได้กำหนดและตัวแปรที่มีค่าที่ไม่ได้กำหนดจะส่งคืน "ไม่ได้กำหนด" ผ่าน typeof
NULL ประเภทดั้งเดิมสุดท้ายผ่าน typeof จะกลับ "วัตถุ" ซึ่งดูแปลก ๆ และถือว่าเป็นข้อผิดพลาดที่ร้ายแรงในข้อกำหนดมาตรฐานดังนั้นเมื่อการเขียนโปรแกรมคุณต้องป้องกันการใช้ประเภทของการตรวจจับประเภท NULL
console.log (typeof null); // "วัตถุ"
เพียงแค่เปรียบเทียบกับ null มักจะมีข้อมูลไม่เพียงพอที่จะตรวจสอบว่าประเภทของค่านั้นถูกกฎหมายหรือไม่ดังนั้น NULL จึงไม่ได้ใช้ในการตรวจจับ
แต่มีข้อยกเว้นหากค่าที่คาดหวังนั้นเป็นโมฆะจริง ๆ คุณสามารถเปรียบเทียบกับ NULL ได้โดยตรง ตัวอย่างเช่น:
// หากคุณต้องการตรวจจับ null ให้ใช้วิธีนี้ var element = document.getElementById ("my-div"); ถ้า (องค์ประกอบ! == null) {element.className = "พบ";}หากองค์ประกอบ DOM ไม่มีอยู่ค่าที่ได้จาก document.getElementById () จะเป็นโมฆะ วิธีนี้จะส่งคืนโหนดหรือส่งคืนค่า NULL เนื่องจาก NULL เป็นเอาต์พุตที่คาดการณ์ได้ในเวลานี้ผลการส่งคืนจึงสามารถตรวจพบได้โดยใช้ตัวดำเนินการตัวตน === หรือตัวดำเนินการที่ไม่ใช่ตัวตน! ==
นอกเหนือจากสตริงตัวเลขบูลีนที่ไม่ได้กำหนดและวัตถุที่กล่าวถึงข้างต้นค่าส่งคืนของตัวดำเนินการ typeof ยังมีฟังก์ชั่น จากมุมมองทางเทคนิคฟังก์ชั่นเป็นวัตถุใน JavaScript ไม่ใช่ชนิดข้อมูล อย่างไรก็ตามฟังก์ชั่นมีคุณสมบัติพิเศษบางอย่างดังนั้นจึงจำเป็นต้องแยกฟังก์ชั่นจากวัตถุอื่น ๆ โดยผู้ประกอบการประเภท คุณลักษณะนี้จะใช้ในฟังก์ชั่นการตรวจจับในภายหลัง
ตรวจจับค่าอ้างอิง
ใน JavaScript ยกเว้นค่าดั้งเดิมค่าอ้างอิงทั้งหมด (เรียกอีกอย่างว่าวัตถุ) ประเภทอ้างอิงที่ใช้กันทั่วไปคือ: วัตถุอาร์เรย์วันที่และ regexp ประเภทอ้างอิงเหล่านี้เป็นวัตถุในตัวใน JavaScript ผู้ประกอบการ typeof ส่งคืน "วัตถุ" เมื่อตัดสินประเภทการอ้างอิงเหล่านี้
console.log (typeof {}); // "object" console.log (typeof []); // "object" console.log (typeof date ใหม่ ()); // "Object" console.log (typeof ใหม่ regexp ()); // "Object" console.log (typeof ใหม่ regexp ()); // "วัตถุ"วิธีที่ดีที่สุดในการตรวจจับประเภทค่าที่อ้างอิงคือการใช้ตัวดำเนินการอินสแตนซ์ของตัวดำเนินการ ไวยากรณ์พื้นฐานของอินสแตนซ์ของคือ:
ค่าอินสแตนซ์ของ constructor // detect วันที่ถ้า (ค่าอินสแตนซ์ของวันที่) {console.log (value.getulyear);} // ตรวจจับข้อผิดพลาด (ค่าอินสแตนซ์ของค่าอินสแตนซ์ของค่า) {ค่าโยน;คุณสมบัติที่น่าสนใจของอินสแตนซ์ของไม่เพียง แต่ตรวจจับตัวสร้างที่สร้างวัตถุนี้ แต่ยังตรวจจับห่วงโซ่ต้นแบบด้วย ห่วงโซ่ต้นแบบมีข้อมูลจำนวนมากรวมถึงรูปแบบการสืบทอดที่ใช้ในการกำหนดวัตถุ ตัวอย่างเช่นโดยค่าเริ่มต้นแต่ละวัตถุสืบทอดมาจากวัตถุดังนั้นอินสแตนซ์ค่าของวัตถุของแต่ละวัตถุจะส่งคืน ture ตัวอย่างเช่น:
var now = new date (); console.log (ตอนนี้อินสแตนซ์ของวัตถุ); // the natureconsole.log (ตอนนี้วันที่ของวันที่); // ตัวดำเนินการ NatureInstanceof ของ NatureInstanceof ยังสามารถตรวจจับประเภทที่กำหนดเองเช่น: Function Person (ชื่อ) {this.name = name;} var me = บุคคลใหม่ ("Nicholas"); console.log (me instanceof object); // the natureconsole.log (ฉันเป็นคนของบุคคล); // ธรรมชาติประเภทบุคคลถูกสร้างขึ้นในรหัสตัวอย่างนี้ ตัวแปรฉันเป็นตัวอย่างของคนดังนั้นฉันจึงอินสแตนซ์ของคนที่เป็นจริง ดังที่ได้กล่าวไว้ข้างต้นวัตถุทั้งหมดถือเป็นอินสแตนซ์ของวัตถุดังนั้นฉันจึงเป็นวัตถุอินสแตนซ์ของวัตถุ
เมื่อตรวจจับประเภทในตัวและแบบกำหนดเองใน JavaScript วิธีที่ดีที่สุดในการทำเช่นนี้คือการใช้ตัวดำเนินการอินสแตนซ์ของตัวดำเนินการซึ่งเป็นวิธีเดียวที่จะทำ
แต่มีข้อ จำกัด ที่ร้ายแรง สมมติว่าทั้งเฟรมเบราว์เซอร์ (เฟรม) มีตัวสร้างบุคคลและอินสแตนซ์ของบุคคล frameapersoninstance ในเฟรม A จะถูกส่งผ่านไปยังเฟรม B ผลลัพธ์ต่อไปนี้จะเป็น:
console.log (frameapersoninstance อินสแตนซ์ของ frameaperson) // ture
console.log (frameapersoninstance instanceof framebperson) // false
แม้ว่าคำจำกัดความของคนทั้งสองจะเหมือนกัน แต่ก็ถือว่าเป็นประเภทที่แตกต่างกันในเฟรมที่แตกต่างกัน มีสองประเภทในตัวที่สำคัญมากที่มีปัญหานี้: อาร์เรย์และฟังก์ชั่นดังนั้นการตรวจจับโดยทั่วไปจะไม่ใช้อินสแตนซ์ของ
ฟังก์ชั่นการตรวจจับ
ในทางเทคนิคการพูดฟังก์ชั่นใน JavaScript เป็นประเภทอ้างอิงและยังมีตัวสร้างฟังก์ชัน แต่ละฟังก์ชั่นเป็นตัวอย่างตัวอย่างเช่น:
ฟังก์ชั่น myfunc () {} // วิธีการเขียนที่ไม่ดี console.log (ฟังก์ชั่นอินสแตนซ์ myfunc); // จริงอย่างไรก็ตามวิธีนี้ไม่สามารถใช้กับเฟรมได้เนื่องจากแต่ละเฟรมมีตัวสร้างฟังก์ชั่นของตัวเอง โชคดีที่ตัวดำเนินการประเภทของตัวดำเนินการยังสามารถใช้สำหรับฟังก์ชั่นส่งคืน "ฟังก์ชั่น"
ฟังก์ชั่น myfunc () {} // วิธีการเขียนที่ดี console.log (typeof myfunc === "ฟังก์ชั่น"); // จริงวิธีที่ดีที่สุดในการตรวจจับฟังก์ชั่นคือการใช้ typeof เพราะสามารถใช้กับเฟรมได้
มีข้อ จำกัด ในการใช้ typeof เพื่อตรวจจับฟังก์ชั่น ใน IE 8 และก่อนหน้านี้คือเบราว์เซอร์ IE, typeof ใช้เพื่อตรวจจับฟังก์ชันนั้นในโหนด DOM ทั้งหมดกลับ "วัตถุ" แทน "ฟังก์ชั่น" ตัวอย่างเช่น:
// iEconsole.log (typeof document.createElement); // "Object" console.log (typeof document.getElementById); // "Object" console.log (typeof document.getElementByTagname); // "Object" console.log (typeof document.getElementByTagname); // "วัตถุ"
ปรากฏการณ์แปลก ๆ นี้เกิดขึ้นเนื่องจากเบราว์เซอร์มีความแตกต่างในการดำเนินการของ DOM ในระยะสั้น IE รุ่นก่อนหน้านี้ไม่ได้ใช้ DOM เป็นวิธี JavaScript ในตัวส่งผลให้ผู้ปฏิบัติงานประเภทในตัวระบุฟังก์ชั่นเหล่านี้เป็นวัตถุ เนื่องจาก DOM ถูกกำหนดอย่างชัดเจนการรู้ว่าสมาชิกวัตถุมีอยู่หมายความว่ามันเป็นวิธีการนักพัฒนามักใช้ตัวดำเนินการในเพื่อตรวจจับวิธีการ DOM เช่น::
// ตรวจจับเมธอด DOM ถ้า ("querySelectorAll" ในเอกสาร) {var images = document.QuerySelectorAll ("IMG");}รหัสนี้ตรวจสอบว่า querySelectorAll ถูกกำหนดไว้ในเอกสารหรือไม่และถ้าเป็นเช่นนั้นให้ใช้วิธีนี้หรือไม่ แม้ว่าจะไม่ใช่วิธีการที่เหมาะ แต่ก็เป็นวิธีที่ปลอดภัยที่สุดในการตรวจสอบว่าวิธี DOM มีอยู่ใน IE 8 และเบราว์เซอร์ก่อนหน้าหรือไม่ ในกรณีอื่น ๆ ทั้งหมดตัวดำเนินการ Typeof เป็นตัวเลือกที่ดีที่สุดสำหรับการตรวจจับฟังก์ชั่น JavaScript
ตรวจจับอาร์เรย์
หนึ่งในปัญหาข้ามโดเมนที่เก่าแก่ที่สุดใน JavaScript คือการผ่านอาร์เรย์ไปมาระหว่างเฟรม นักพัฒนาค้นพบในไม่ช้าว่าอินสแตนซ์ของอาร์เรย์ไม่สามารถส่งคืนผลลัพธ์ที่ถูกต้องในสถานการณ์นี้ ดังที่ได้กล่าวไว้ข้างต้นแต่ละเฟรมมีตัวสร้างอาร์เรย์ของตัวเองดังนั้นอินสแตนซ์ในเฟรมหนึ่งจะไม่ได้รับการยอมรับในเฟรมอื่น
มีงานวิจัยมากมายเกี่ยวกับวิธีการตรวจจับประเภทอาร์เรย์ใน JavaScript และในที่สุด Kangax ก็ให้ทางออกที่หรูหรา:
ฟังก์ชั่น isarray (value) {return object.prototype.toString.call (value) === "[อาร์เรย์วัตถุ]";}Kangax พบว่าการเรียกใช้วิธี ToString () ในตัวของค่าส่งคืนสตริงมาตรฐานผลลัพธ์ในเบราว์เซอร์ทั้งหมด สำหรับอาร์เรย์สตริงที่ส่งคืนคือ "[อาร์เรย์วัตถุ]" และไม่จำเป็นต้องพิจารณาเฟรมใดที่สร้างอินสแตนซ์อาร์เรย์ วิธีนี้มักจะมีประโยชน์มากเมื่อระบุวัตถุในตัว แต่โปรดอย่าใช้วิธีนี้สำหรับวัตถุที่กำหนดเอง
ecmascript5 แนะนำ array.isarray () อย่างเป็นทางการใน JavaScript จุดประสงค์เดียวคือการตรวจสอบอย่างถูกต้องว่าค่าเป็นอาร์เรย์หรือไม่ เช่นเดียวกับฟังก์ชั่นของ Kangax array.isarray () ยังสามารถตรวจจับค่าที่ส่งผ่านเฟรมได้ดังนั้นไลบรารีคลาส JavaScript จำนวนมากในปัจจุบันใช้วิธีนี้ในทำนองเดียวกัน
ฟังก์ชั่น isarray (value) {ถ้า (typeof array.isarray === "function") {return array.isarray (ค่า);} else {return object.prototype.toString.call (value) === "[อาร์เรย์วัตถุ]";}}}}IE 9+, Firefox 4+, Safari 5+, Opera 10.5+ และ Chrome ทั้งหมดใช้วิธี array.isarray ()
ตรวจจับคุณสมบัติ
อีกสถานการณ์หนึ่งที่ null (และไม่ได้กำหนด) คือเมื่อตรวจพบว่าแอตทริบิวต์มีอยู่ในวัตถุเช่น:
// การเขียนที่ไม่ดี: ตรวจจับค่าเท็จถ้า (Object [PropertyName]) {// บางรหัส} // การเขียนที่ไม่ดี: เปรียบเทียบกับ null ถ้า (object [propertyName]! = null) {// รหัสบางตัว} // การเขียนที่ไม่ดี: เปรียบเทียบกับ undefined if (object [propertyName]!การตัดสินแต่ละครั้งในรหัสข้างต้นจะตรวจสอบค่าของแอตทริบิวต์ด้วยชื่อที่กำหนดแทนที่จะตัดสินว่าแอตทริบิวต์ที่อ้างถึงชื่อที่กำหนดนั้นมีอยู่หรือไม่ ในการตัดสินครั้งแรกผลลัพธ์จะเกิดขึ้นเมื่อค่าคุณสมบัติเป็นค่าเท็จเช่น: 0, "" (สตริงว่าง), เท็จ, โมฆะและไม่ได้กำหนดหลังจากทั้งหมดเหล่านี้เป็นค่าทางกฎหมายของทรัพย์สิน
วิธีที่ดีที่สุดในการพิจารณาว่าแอตทริบิวต์มีอยู่คือการใช้ตัวดำเนินการในหรือไม่ ผู้ประกอบการเพียงตัดสินว่าทรัพย์สินมีอยู่โดยไม่ต้องอ่านมูลค่าของทรัพย์สินหรือไม่ หากคุณสมบัติของวัตถุอินสแตนซ์มีอยู่หรือสืบทอดมาจากต้นแบบของวัตถุตัวดำเนินการในจะส่งคืนจริง ตัวอย่างเช่น:
var object = {count: 0, ที่เกี่ยวข้อง: null}; // การเขียนที่ดีถ้า ("count" ในวัตถุ) {// รหัสที่นี่จะถูกดำเนินการ} // การเขียนที่ไม่ดี: ตรวจจับค่าเท็จถ้า (วัตถุ ["count"]) {// รหัสที่นี่จะไม่ถูกดำเนินการ} // การเขียนที่ดีถ้า ("ที่เกี่ยวข้อง" {// รหัสที่นี่จะไม่ถูกดำเนินการ}หากคุณเพียงต้องการตรวจสอบว่ามีคุณสมบัติบางอย่างของวัตถุอินสแตนซ์ให้ใช้เมธอด HasownProperty () หรือไม่ วัตถุ JavaScript ทั้งหมดที่สืบทอดมาจากวัตถุมีวิธีนี้ หากคุณสมบัตินี้มีอยู่ในอินสแตนซ์มันจะส่งคืนจริง (หากคุณสมบัตินี้มีอยู่เฉพาะในต้นแบบมันจะส่งคืนเท็จ) ควรสังเกตว่าใน IE 8 และเวอร์ชันก่อนหน้าของ IE วัตถุ DOM ไม่ได้รับมรดกจากวัตถุดังนั้นวิธีนี้จึงไม่รวม นั่นคือคุณควรตรวจสอบว่ามีวิธีการ HasownProperty () ของวัตถุ DOM ก่อนที่จะเรียกใช้หรือไม่
// นี่เป็นวิธีที่ดีในการเขียนถ้า (object.hasownproperty ("เกี่ยวข้อง")) {// เรียกใช้รหัสที่นี่} // ถ้าคุณไม่แน่ใจว่าเป็นวัตถุ DOM หรือไม่จากนั้นเขียนว่า ("HasownProperty" ใน Object && วัตถุเนื่องจากมี IE 8 และรุ่นก่อนหน้าของ IE เมื่อตัดสินว่าคุณลักษณะของวัตถุอินสแตนซ์มีอยู่หรือไม่ฉันจึงชอบใช้ตัวดำเนินการใน HasownProperty () จะใช้เฉพาะเมื่อตัดสินคุณสมบัติอินสแตนซ์
ไม่ว่าเมื่อใดที่คุณต้องการตรวจจับการมีอยู่ของทรัพย์สินให้ใช้ผู้ให้บริการในหรือ HasownProperty () การทำเช่นนี้สามารถหลีกเลี่ยงข้อบกพร่องมากมาย
ข้างต้นคือการตรวจจับ JavaScript ของค่าดั้งเดิมค่าอ้างอิงและแอตทริบิวต์ที่แนะนำโดยตัวแก้ไข ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับทุกคนในเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!