โอเปอเรเตอร์ Double Tilde (~~) คือการใช้ Bitwise NOT (~) สองครั้งติดกัน ใช้เป็น ทางเลือกเร็วกว่า Math.floor() สำหรับจำนวนบวก เพื่อตัดทศนิยม (Truncate toward zero)
ตัวอย่างโค้ด
<html>
<body>
<script>
var a = 2.9;
var b = ~~a; // 2
var c = Math.floor(a); // 2
var d = ~~b === c; // true
document.write(b + "<br>" + c + "<br>" + d);
</script>
</body>
</html>
ทำไมถึงทำงานได้?
~ครั้งแรก: กลับบิตทั้งหมด (One's Complement) →~2.9 = ~2 = -3~ครั้งที่สอง: กลับบิตอีกครั้ง →~(-3) = 2- ผลลัพธ์: ส่วนจำนวนเต็มของตัวเลข (ตัดทศนิยมทิ้ง)
ตารางเปรียบเทียบ
| ค่า | ~~x | Math.floor(x) | Math.trunc(x) |
|---|---|---|---|
| 2.9 | 2 | 2 | 2 |
| 2.1 | 2 | 2 | 2 |
| -2.9 | -2 | -3 | -2 |
| -2.1 | -2 | -3 | -2 |
สำคัญ: ~~ ทำงานเหมือน Math.trunc() (ตัดทศนิยม) ไม่ใช่ Math.floor() (ปัดลง) สำหรับจำนวนลบ
ข้อดีและข้อเสีย
| ข้อดี | ข้อเสีย |
|---|---|
| เร็วกว่า Math.floor (ในบาง Engine) | ทำงานได้เฉพาะ 32-bit Integer (-2,147,483,648 ถึง 2,147,483,647) |
| สั้น กระชับ | อ่านยาก ไม่ชัดเจน (Magic Number) |
| ไม่ต้องเรียก Function | พฤติกรรมต่างกับ Math.floor สำหรับจำนวนลบ |
กรณีที่ควรหลีกเลี่ยง
- ตัวเลขใหญ่กว่า 2^31-1 (Overflow)
- โค้ดที่ต้องการความชัดเจน (Readability)
- จำนวนลบที่ต้องการ Math.floor จริงๆ
- โค้ดสมัยใหม่ ควรใช้
Math.trunc()(ES2015) แทน
การใช้งานจริง (Legacy Code)
// Array index safety var index = ~~(offset / size); // Pixel snapping var x = ~~(element.offsetLeft / 10) * 10; // Quick integer conversion var num = ~~"123"; // 123 var nan = ~~"abc"; // 0 (NaN -> 0)
สรุป
~~ เป็น Legacy Trick สำหรับประสิทธิภาพ ในโค้ดสมัยใหม่ ควรใช้ Math.trunc(), Math.floor(), หรือ parseInt() ที่ชัดเจนและปลอดภัยกว่า