JavaScript "isNaN(true)" returns false
- Sathit Jittanupat
- 13 ธ.ค. 2567
- ยาว 1 นาที
JavaScript เป็นภาษาที่คอยตบกระโหลกเตือนให้คุณต้องถ่อมตัวเสมอ วันดีคืนดีจะมีคำสั่งที่คุณคิดว่ารู้จักดีแล้ว แต่เมื่อเรียกใช้แล้วทำให้ประหลาดใจกับผลของมันว่าไม่เป็นอย่างที่คิด ผมเคยตกหลุมกับดัก Math.round เมื่อหลายปีก่อนจนจำได้แม่นยำ และคราวนี้เจออีก
isNaN
ที่มาของเรื่อง ผมออกแบบคำสั่ง config ในโปรแกรมให้สามารถกำหนดเป็น true , false , หรือตัวเลขใดๆ ก็ได้
ใช้สำหรับควบคุมเงื่อนไขการบันทึก log เมื่อมีใครเปลี่ยนการตั้งค่าการทำงาน
false บันทึก log โดยไม่ต้องแจ้งเตือน
true แจ้งเตือนทุกครั้งให้ระบุเหตุผลของการแก้ไข ก่อนบันทึก log
ตัวเลข จำนวนวันที่ต้องการเว้นช่วงแจ้งเตือน เช่น 1 หมายถึง ภายใน 1 วันหากมีการแก้ไขหลายครั้ง จะแจ้งเตือนให้บันทึกเหตุผลแค่ครั้งแรกครั้งเดียว
ความตั้งใจของผม เปิดให้เลือกกำหนดเงื่อนไขสำหรับแต่ละโปรเจคท์ได้เอง เผื่อว่าไม่อยากให้โปรแกรมแจ้งเตือนถามเหตุผลพร่ำเพรื่อเกินไป บางครั้งช่วงที่ขึ้นระบบใหม่การตั้งค่าอาจติดพันต่อเนื่อง ซึ่งแตกต่างจากช่วงที่ระบบลงตัวแล้ว อารมณ์ของคนทำงานจะต่างกัน

NaN ย่อมาจาก Not A Number ตามความเข้าใจ(ผิด)ของผม จึงใช้คำสั่ง isNaN ตรวจสอบว่าค่านั้นเป็นตัวเลขหรือไม่ โดยคาดหวังว่า isNaN(true) ควรได้ผลลัพธ์ว่า ไม่เป็นตัวเลข
หลังจากที่อัพเดทโปรแกรมไปใช้งานไปได้สองวัน กลับมาตรวจสอบการทำงาน ปรากฏว่าเมื่อตั้งค่าเป็น true กลับไม่ยอมแจ้งเตือนให้ระบุเหตุผลทุกครั้ง แต่ทำงานเหมือนกับใส่ค่าตัวเลขจำนวนวัน พยายามตรวจสอบโน่นนี่นั่น จนสุดท้ายก็เลย เอ๊ะ หรือว่า true จะถูกตีความว่าเป็นค่าตัวเลข (enum) เหมือนบางภาษา
สรุปว่าจริงตามนั้น ทีแรกเข้าใจเอาเองว่าเฉพาะ Number (integer/float) หรือ ข้อความตัวเลขเท่านั้น อะไรที่ดูไม่เหมือนตัวเลขไม่ควรนับรวม ไม่คิดว่า Boolean, Array หรือ Empty String จะถูกเหมารวมว่าเป็นค่าตัวเลขด้วย โอ มายก็อด
Boolean isNaN(true) และ isNaN(false) เธอตอบว่าเป็นตัวเลข เพราะ +true มีค่าเป็น 1 และ +false มีค่าเป็น 0
Empty String isNaN("") และ isNaN(" ") มีหรือไม่มี space อยู่ด้วย ก็ตอบว่าเป็นตัวเลข เราสามารถแปลงเป็น Number ด้วยคำสั่ง (+"") ได้เท่ากับ 0 รวมทั้ง isNaN(" 1") ก็ถือว่าเป็นตัวเลขเหมือนกัน
Array isNaN([]) และ isNaN([""]) และ isNaN([" "]) เธอก็ยังบอกว่าเป็นตัวเลขเช่นกัน ขัดความรู้สึกยังไงก็ไม่รู้
คนเขียน JavaScript น่าจะเป็นคนที่เข้าใจอารมณ์ซับซ้อนของคนอื่นได้ดี

สำหรับกรณีของผม แก้ไขโดยเขียนโค้ดได้ประมาณนี้
if (alert && alert!==true && !isNaN(alert)) เมื่อเข้าใจแล้วไม่ยาก หาทางเขียนโค้ดตรวจละเอียดตามวัตถุประสงค์กันเองนะครับ
Math.round
แถมเล่าเรื่องหลุมพรางเก่าให้อีกสั้นๆ เคยเขียนเล่าไปแล้ว เจอตอนที่ทำใบลดหนี้ปัดเศษคำนวณภาษี
กรณีค่าสินค้ามีเศษสตางค์ .50 แล้วคำนวณภาษีอัตรา 7%
ปกติค่าสินค้า 10.50 คำนวณภาษีได้ 0.735 ปัดเศษเป็น 0.74
เราสามารถใช้คำสั่ง Math.round(10.50 * 7) / 100 ได้ 0.74 ถูกต้อง
ถ้าลดหนี้เป็นค่าติดลบ -10.50 คำนวณภาษีได้ -0.735 ก็ควรปัดเศษเป็น -0.74
แต่ Math.round(-10.50 * 7) / 100 กลับได้ 0.73 ไม่เท่ากัน
กลายเป็นว่าตอนลดหนี้คืนเงินค่าภาษีไม่ครบ

เรื่องนี้ใครใช้ JavaScript แล้วคำนวณปัดเศษต้องระวังให้ดี
ผมแก้โดยเขียนฟังก์ชั่น round ใช้เอง ตรวจก่อน ถ้าเป็นค่าลบให้กลับเป็นค่าบวกคำนวณปัดเศษ เสร็จ แล้วค่อยกลับค่าเป็นลบ



ความคิดเห็น