JavaScript
Built-in Classes
Number
เรียนรู้ `Number` built-in class — static constants, static methods, การแปลงค่าด้วย `Number()` และ prototype methods สำหรับใช้ในงานจริง
`Number` คือ built-in class ที่ JavaScript เตรียม static methods และค่าคงที่มาให้
`Number` เป็น built-in class ใน JavaScript — เป็น object ระดับ global ที่มี **static properties** (ค่าคงที่เช่น `Number.MAX_SAFE_INTEGER`) และ **static methods** (ฟังก์ชันเช่น `Number.isInteger()`) ให้เรียกใช้ได้ทันที โดยไม่ต้องสร้าง instance ด้วย `new` บาง method ที่เรียนไปแล้วเป็น static method ของ `Number` ทั้งนั้น: `Number.isNaN()` (บทที่ 86) และ `Number.isFinite()` (บทที่ 87) — เรียกผ่าน `Number.` โดยตรง `Number` ต่างจาก primitive `number`: - `let price = 299;` — ตัวแปร `price` เป็น primitive `number` - `Number` — เป็น class/object ที่เก็บ static methods และ constants เวลาเราเรียก method บน primitive เช่น `(42).toString()` — JavaScript จะทำ **auto-boxing** โดย wrap `42` เป็น `Number` object ชั่วคราว เรียก method แล้วคืนค่าเป็น primitive ทันที นอกจากนี้ `Number()` ยังใช้เป็น **conversion function** เพื่อแปลงค่าจาก type อื่นเป็นตัวเลข — `Number("123")` → `123` — โดยไม่ต้องใช้ `new` (ซึ่งการทำ `new Number()` จะสร้าง wrapper object ที่ไม่แนะนำให้ใช้)
// static properties — ค่าคงที่ของ Number
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
// static methods — เรียกโดยตรง ไม่ต้องสร้าง instance
console.log(Number.isInteger(42)); // true
console.log(Number.isInteger(3.14)); // false
// Number() ใช้เป็น converter
console.log(Number("299")); // 299
console.log(Number("")); // 0
// auto-boxing — primitive เรียก method ได้ชั่วคราว
console.log((42).toString(2)); // "101010"
console.log((299).toFixed(2)); // "299.00"- `Number` เป็น built-in class — มี static methods และ constants ให้เรียกใช้ได้ทันที
- primitive `number` กับ `Number` class เป็นคนละอย่าง — แต่มันทำงานร่วมกันผ่าน auto-boxing
- ใช้ `Number()` เป็น function แปลงค่า — อย่าใช้ `new Number()`
- `Number.isNaN()` และ `Number.isFinite()` ที่เรียนไปแล้วเป็น static method ของ `Number`
Static constants — ตัวเลขพิเศษที่ `Number` มีให้
`Number` มี static properties ที่เป็นค่าคงที่ไว้ใช้ตรวจสอบขอบเขตและพฤติกรรมของตัวเลขใน JavaScript ค่าเหล่านี้มีประโยชน์เมื่อต้องตัดสินใจว่าตัวเลขที่คุณมีนั้นใช้คำนวณต่อได้ไหม `Number.MAX_VALUE` (≈ 1.79e+308) — ค่าที่ใหญ่ที่สุดที่ `number` เก็บได้ เกินนี้จะเป็น `Infinity` `Number.MIN_VALUE` (≈ 5e-324) — ค่าบวกที่เล็กที่สุดที่ `number` เก็บได้ (ไม่ใช่ค่าลบที่เล็กที่สุด) **Safe Integer** — จำนวนเต็มที่รับประกันว่าแสดงผลแม่นยำใน IEEE 754 double-precision: `Number.MAX_SAFE_INTEGER` = 9007199254740991 (2⁵³ − 1) `Number.MIN_SAFE_INTEGER` = -9007199254740991 `Number.EPSILON` (≈ 2.22e-16) — ระยะห่างที่น้อยที่สุดระหว่าง 1 กับเลขทศนิยมที่มากกว่า 1 — ใช้ในการเปรียบเทียบทศนิยมแบบมี tolerance `Number.POSITIVE_INFINITY`, `Number.NEGATIVE_INFINITY`, `Number.NaN` — ค่าคงที่แทน infinity และ NaN (ใช้แทนการเขียน literal โดยตรง)
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MIN_VALUE); // 5e-324
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
console.log(Number.EPSILON); // 2.220446049250313e-16
console.log(Number.POSITIVE_INFINITY); // Infinity
console.log(Number.NEGATIVE_INFINITY); // -Infinity
console.log(Number.NaN); // NaN| ค่าคงที่ | ใช้เมื่อไหร่ | ตัวอย่าง use case |
|---|---|---|
| `Number.MAX_SAFE_INTEGER` | เช็กก่อนคำนวณตัวเลขใหญ่มาก | ตรวจสอบว่า ID จาก database ยังอยู่ในช่วง safe ก่อนใช้เป็น key |
| `Number.EPSILON` | เปรียบเทียบทศนิยมแบบมี tolerance | `Math.abs(a - b) < Number.EPSILON` แทน `a === b` |
| `Number.MAX_VALUE` | ตรวจสอบ overflow | ดักก่อนที่ค่าจะกลายเป็น `Infinity` จากการคำนวณซ้ำ |
| `Number.POSITIVE_INFINITY` | เปรียบเทียบผลลัพธ์ที่อาจ overflow | `result === Number.POSITIVE_INFINITY` → ดัก division by zero |
- `Number.MAX_SAFE_INTEGER` มีประโยชน์ที่สุดในงานจริง — ใช้ตรวจสอบก่อนคำนวณยอดเงิน, ID, หรือค่าที่ต้องการความแม่น
- `Number.EPSILON` เป็นค่า tolerance ที่น้อยมาก — ใช้เปรียบเทียบทศนิยม แทน `===` ตรง ๆ
- `Number.MAX_VALUE` / `Number.MIN_VALUE` ไม่ค่อยใช้ในงานทั่วไป — มีไว้ตรวจ overflow
- `Number.POSITIVE_INFINITY` / `Number.NEGATIVE_INFINITY` / `Number.NaN` — ใช้แทน literal เพื่อให้อ่านเจตนาชัด
`Number.parseInt()` และ `Number.parseFloat()` — ดึงตัวเลขออกจาก string
`Number.parseInt(string)` ดึงตัวเลขจำนวนเต็มจากต้น string — หยุดอ่านทันทีที่เจอตัวอักษรที่ไม่ใช่ตัวเลข `Number.parseFloat(string)` เหมือนกันแต่ดึงเลขทศนิยมได้ **Use case หลัก**: parse CSS value (`"1280px"`), data attribute (`"3.14cm"`), หรือ user input ที่มีหน่วยปนมา `Number.parseInt` รับ parameter ตัวที่สองเป็น **radix** (ฐานตัวเลข) เช่น `Number.parseInt("101", 2)` จะอ่าน "101" ในฐาน 2 ได้ผลลัพธ์เป็น 5 ต่างจาก global `parseInt()` / `parseFloat()` ยังไง? — ใน JavaScript สมัยใหม่ทั้งสองทำงานเหมือนกัน (global `parseInt` ชี้ไปที่ `Number.parseInt` ใน ES6+) แต่การเขียน `Number.parseInt` ทำให้เจตนาชัดเจนว่าเป็น static method ของ `Number` — เขียนโค้ดอ่านง่ายกว่า
// Number.parseInt — อ่านเลขจำนวนเต็มจากต้น string
console.log(Number.parseInt("1280px")); // 1280
console.log(Number.parseInt("3.14cm")); // 3 ← หยุดที่ "."!
console.log(Number.parseInt("42")); // 42
console.log(Number.parseInt("abc42")); // NaN ← ไม่มีเลขที่ต้น string
// Number.parseFloat — อ่านเลขทศนิยมจากต้น string
console.log(Number.parseFloat("3.14cm")); // 3.14
console.log(Number.parseFloat("12.5.3")); // 12.5 ← จุดแรกเท่านั้น
console.log(Number.parseFloat("width:99")); // NaN
// radix — อ่านในฐานที่กำหนด
console.log(Number.parseInt("101", 2)); // 5 ← binary → decimal
console.log(Number.parseInt("ff", 16)); // 255 ← hex → decimal| method | อ่านอะไร | ตัวอย่าง | ผลลัพธ์ |
|---|---|---|---|
| `Number.parseInt(s)` | จำนวนเต็มจากต้น string | `Number.parseInt("1280px")` | `1280` |
| `Number.parseFloat(s)` | เลขทศนิยมจากต้น string | `Number.parseFloat("3.14cm")` | `3.14` |
| `Number.parseInt(s, r)` | จำนวนเต็มในฐาน r จากต้น string | `Number.parseInt("ff", 16)` | `255` |
- ใช้ `Number.parseInt` กับ `Number.parseFloat` เมื่อค่ามีหน่วยต่อท้าย — ต้องการแค่ตัวเลข
- ระวัง: `Number.parseInt("3.14cm")` ได้ `3` ไม่ใช่ `3.14` — ใช้ `parseFloat` ถ้าต้องการทศนิยม
- radix ช่วยแปลงเลขฐาน 2, 8, 16 กลับเป็น decimal — มีประโยชน์ตอน parse binary flag หรือ hex color
- เลือก `Number.parseInt` มากกว่า `parseInt` เพื่อให้โค้ดสื่อความหมายชัดเจน
`Number.isInteger()` และ `Number.isSafeInteger()` — เช็กว่าเป็นจำนวนเต็มที่ปลอดภัย
`Number.isInteger(value)` ตรวจสอบว่า `value` เป็นจำนวนเต็มหรือไม่ — คืน `true` สำหรับ `42`, `0`, `-7` แต่คืน `false` สำหรับ `3.14`, `NaN`, `Infinity` `Number.isSafeInteger(value)` ตรวจสอบว่า `value` เป็นจำนวนเต็มและอยู่ในช่วง safe integer (`[-(2⁵³-1), 2⁵³-1]`) หรือไม่ — จำนวนเต็มที่เกินช่วงนี้จะเริ่มมีปัญหาเรื่องความแม่นยำ เช่น `9007199254740991 + 1` กับ `9007199254740991 + 2` ได้ผลลัพธ์เท่ากัน **Use case**: ใช้ `Number.isInteger` ในการ validate user input เช่น field 'จำนวนสินค้า' ต้องเป็นจำนวนเต็มเท่านั้น ใช้ `Number.isSafeInteger` ก่อนนำค่าจำนวนเต็มขนาดใหญ่ไปใช้ในการคำนวณที่ต้องการความแม่น เช่น ยอดเงิน, database ID
// Number.isInteger — เป็นจำนวนเต็มหรือไม่
console.log(Number.isInteger(42)); // true
console.log(Number.isInteger(0)); // true
console.log(Number.isInteger(-17)); // true
console.log(Number.isInteger(3.14)); // false
console.log(Number.isInteger(NaN)); // false
console.log(Number.isInteger(Infinity)); // false
console.log(Number.isInteger("42")); // false ← string ไม่ใช่ number
// Number.isSafeInteger — อยู่ใน safe range หรือไม่
console.log(Number.isSafeInteger(42)); // true
console.log(Number.isSafeInteger(9007199254740991)); // true ← MAX_SAFE
console.log(Number.isSafeInteger(9007199254740992)); // false ← เกิน!
console.log(Number.isSafeInteger(3.14)); // false ← ไม่ใช่ integer
// ทำไม safe integer ถึงสำคัญ
const big = 9007199254740991;
console.log(big + 1); // 9007199254740992 ✅
console.log(big + 2); // 9007199254740992 ❌ ได้เท่ากัน!| method | ตรวจสอบอะไร | ใช้เมื่อไหร่ |
|---|---|---|
| `Number.isInteger(v)` | เป็นจำนวนเต็มหรือไม่ | validate จำนวนสินค้า, จำนวนคน, array index |
| `Number.isSafeInteger(v)` | เป็นจำนวนเต็มที่อยู่ใน safe range หรือไม่ | validate database ID, ยอดเงิน, ค่าที่ต้องคำนวณแม่น |
- `Number.isInteger` ไม่ทำ type coercion — `Number.isInteger("42")` เป็น `false`
- `Number.isSafeInteger` คืน `false` สำหรับเลขทศนิยมทุกค่า — ถึงแม้ค่าจะอยู่ใน range
- safe integer เกี่ยวข้องกับ IEEE 754 double-precision — จำนวนเต็มที่เกิน 2⁵³-1 จะเริ่มมีปัญหา precision
- ใช้ `Number.isSafeInteger` ก่อนนำค่าจาก API/database ไปคำนวณต่อ
`Number()` — แปลงค่าจาก type อื่นให้เป็น number
`Number(value)` เป็น built-in function ที่แปลง `value` จาก type ใด ๆ ให้เป็น `number` — ใช้บ่อยมากในการ normalize ค่าจาก form, API, หรือ localStorage ก่อนนำไปคำนวณ กฎการแปลง: - string ที่เป็นตัวเลขล้วน → ตัวเลข (`Number("42")` → `42`, `Number("3.14")` → `3.14`) - string ว่างหรือ whitespace → `0` (`Number("")` → `0`, `Number(" ")` → `0`) - string ที่ไม่ใช่ตัวเลข → `NaN` (`Number("hello")` → `NaN`, `Number("42px")` → `NaN`) - `true` → `1`, `false` → `0` - `null` → `0`, `undefined` → `NaN` - object/array → `NaN` (ยกเว้น array ที่มี element เดียวที่เป็นตัวเลข) `Number()` ต่างจาก `parseInt`/`parseFloat` ตรงที่ `Number()` ต้องการ string ที่เป็นตัวเลขล้วน ๆ — ไม่ยอมให้มีตัวอักษรปน ถ้ามีจะคืน `NaN`
// string → number
console.log(Number("42")); // 42
console.log(Number("3.14")); // 3.14
console.log(Number("")); // 0
console.log(Number(" 99 ")); // 99 ← trim whitespace
console.log(Number("42px")); // NaN ← มีตัวอักษรปน
console.log(Number("hello")); // NaN
// boolean → number
console.log(Number(true)); // 1
console.log(Number(false)); // 0
// null / undefined → number
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
// Number() vs parseInt — ต่างกันตรงนี้
console.log(Number("42px")); // NaN ← ล้มเหลว
console.log(Number.parseInt("42px")); // 42 ← ดึงตัวเลขได้| สถานการณ์ | ใช้ฟังก์ชันไหน | เหตุผล |
|---|---|---|
| ค่าจาก input type="number" | `Number(value)` | input type="number" ให้ string ที่เป็นตัวเลขล้วน |
| ค่าที่อาจมีหน่วยปน เช่น "1280px" | `Number.parseInt(value)` | parseInt ทน string ที่มีตัวอักษรต่อท้าย |
| ต้องการให้ "" หรือ " " เป็น 0 | `Number(value)` | Number() แปลง empty string เป็น 0 |
| ต้องการดัก invalid input | `Number(value)` + `Number.isNaN()` | ถ้าแปลงไม่ได้ → NaN → ใช้ Number.isNaN เช็ก |
- `Number("42px")` → `NaN` แต่ `Number.parseInt("42px")` → `42` — เลือกให้เหมาะกับ input
- `Number("")` → `0` — ระวัง: ถ้า empty string ควรเป็น error ให้ตรวจสอบก่อนเรียก `Number()`
- ใช้ `Number()` คู่กับ `Number.isNaN()` เพื่อกรองค่าที่แปลงไม่ได้
- อย่าใช้ `Number()` กับค่าที่อาจมีหน่วยปน — ใช้ `parseInt` หรือ `parseFloat` แทน
Prototype methods — `.toString()` กับ `.toExponential()`
`Number.prototype` มี methods ที่ใช้กับ instance ของ number — เรียกผ่าน primitive โดย auto-boxing ได้เลย **`.toString(radix)`** — แปลงตัวเลขเป็น string ในฐานที่กำหนด (ค่า default คือฐาน 10) เหมาะสำหรับการแสดงผลเลขฐานต่าง ๆ: `(255).toString(16)` → `"ff"` (hex) `(10).toString(2)` → `"1010"` (binary) radix รับค่าได้ตั้งแต่ 2 ถึง 36 **`.toExponential(fractionDigits)`** — แปลงตัวเลขเป็น scientific notation (`"1.23e+5"` รูปแบบ) เหมาะสำหรับแสดงผลตัวเลขที่ใหญ่มากหรือเล็กมากใน UI `(123456).toExponential(2)` → `"1.23e+5"` **`.valueOf()`** — คืนค่า primitive number จาก Number object — ปกติ JavaScript เรียกให้อัตโนมัติ ไม่จำเป็นต้องเรียกเอง methods ที่เรียนไปแล้วในบทก่อน: `.toFixed()` (บทที่ 84) และ `.toPrecision()` (บทที่ 85) ก็เป็น prototype method ของ `Number` เช่นกัน
// .toString(radix) — แสดงผลในฐานต่าง ๆ
const value = 255;
console.log(value.toString(2)); // "11111111" ← binary
console.log(value.toString(8)); // "377" ← octal
console.log(value.toString(10)); // "255" ← default
console.log(value.toString(16)); // "ff" ← hex
// radix 36 — ใช้สร้าง short ID
console.log((123456).toString(36)); // "2n9c"
// .toExponential(fractionDigits) — scientific notation
console.log((123456).toExponential(2)); // "1.23e+5"
console.log((0.000123).toExponential(2)); // "1.23e-4"
// .valueOf() — ใช้คืนค่าดั้งเดิมจาก wrapper
const numObj = new Number(42);
console.log(numObj.valueOf()); // 42
console.log(typeof numObj); // "object"
console.log(typeof numObj.valueOf()); // "number"
// .toFixed() / .toPrecision() — เรียนแล้วในบท 84-85
console.log((3.14159).toFixed(2)); // "3.14"
console.log((3.14159).toPrecision(3)); // "3.14"| method | คืนค่า | ใช้เมื่อไหร่ |
|---|---|---|
| `.toString(radix)` | `string` | แปลงเลขเป็น binary/hex/octal — dev tools, encoding, display |
| `.toExponential(n)` | `string` | แสดงเลขใหญ่มากหรือเล็กมากในรูปแบบ scientific notation |
| `.valueOf()` | `number` | JavaScript เรียกให้อัตโนมัติ — แทบไม่ต้องใช้เอง |
- เขียน `(42).toString(2)` — ต้องมีวงเล็บคลุมตัวเลข เพราะ `.` ตัวแรก JavaScript จะมองว่าเป็นทศนิยม
- radix 36 ใช้สร้าง short ID จาก timestamp ได้ — `Date.now().toString(36)`
- ทุก method บน prototype คืนค่าเป็น `string` — ถ้าจะคำนวณต่อต้องแปลงกลับด้วย `Number()`
- `.toFixed()` และ `.toPrecision()` เป็น prototype method ของ `Number` เช่นกัน — เรียนแล้วในบทก่อน