JavaScript
Number Methods
Math.min / Math.max
เรียนรู้ Math.min() และ Math.max() สำหรับหาค่าน้อยสุดและมากสุด ใช้กับ array ด้วย spread operator และจำกัดค่าในช่วงด้วย clamping
Math.min / Math.max หาค่าน้อยสุดและมากสุด
`Math.min()` และ `Math.max()` เป็น static method บน `Math` สำหรับหาค่าน้อยที่สุดและมากที่สุดจาก argument ที่ส่งเข้าไป ทั้งสอง method: - รับ argument กี่ตัวก็ได้ (รวมถึง 0 ตัว) - คืนค่าเป็น `number` - ใช้ได้กับทุกประเภทข้อมูลที่เป็นตัวเลข ใช้จริง: หาคะแนนสูงสุด, ตรวจสอบขอบเขต, จำกัดค่า (clamping), validation
// Math.min — หาค่าน้อยสุด
console.log(Math.min(3, 7)); // 3
console.log(Math.min(3, 7, 1, 9)); // 1
// Math.max — หาค่ามากสุด
console.log(Math.max(3, 7)); // 7
console.log(Math.max(3, 7, 1, 9)); // 9
// ใช้ตัวแปรก็ได้
const a = 15;
const b = 8;
console.log(Math.min(a, b)); // 8
console.log(Math.max(a, b)); // 15- `Math.min(...args)` คืนค่าน้อยที่สุดจาก argument ทั้งหมด
- `Math.max(...args)` คืนค่ามากที่สุดจาก argument ทั้งหมด
- รับ argument กี่ตัวก็ได้ — 2, 5, 100 ตัว หรือไม่ใส่เลยก็ได้
- ถ้ามี argument ที่เป็น `NaN` → ผลลัพธ์จะเป็น `NaN` เสมอ
หาค่าน้อยสุด/มากสุดจาก array ด้วย spread operator
วิธีที่ใช้บ่อยที่สุดคือนำ array มาหาค่าน้อยสุดหรือมากสุด โดยใช้ **spread operator** (`...`) กระจาย element ของ array เป็น argument แต่ละตัว ```javascript Math.min(...array) Math.max(...array) ``` ถ้าส่ง array เข้าไปโดยไม่ใช้ spread (`Math.min(array)`) จะได้ `NaN` เพราะ `Math.min` ได้รับ argument แค่ 1 ตัวที่เป็น array — ซึ่งไม่ใช่ number
const scores = [72, 95, 88, 61, 100, 83];
// ✅ ใช้ spread operator — กระจาย array เป็น argument แต่ละตัว
console.log(Math.max(...scores)); // 100
console.log(Math.min(...scores)); // 61
// ❌ ไม่ใช้ spread — ส่ง array ทั้งก้อนเข้าไป
console.log(Math.max(scores)); // NaN ← array ไม่ใช่ number!
// เทียบ: spread แบบ manual
console.log(Math.max(72, 95, 88, 61, 100, 83)); // 100 — เหมือนกันข้อจำกัดของ spread กับ array ขนาดใหญ่
spread operator กระจายทุก element เป็น argument ของ function ถ้า array มีขนาดใหญ่มาก (เช่น 100,000+ elements) อาจเกิด **Maximum call stack size exceeded** ได้ สำหรับ array ขนาดใหญ่ ให้ใช้ `array.reduce()` แทน: ```javascript const max = arr.reduce((a, b) => Math.max(a, b)); ```
- ใช้ `Math.min(...array)` หรือ `Math.max(...array)` กับ array ขนาดปกติ
- ถ้าไม่ใช้ spread → `Math.min(array)` ได้ `NaN` เพราะส่ง array เข้าไปทั้งก้อน
- spread operator มาจากบท Modern Data Syntax — `...` กระจาย array เป็น argument แยก
- array ขนาดใหญ่มาก → ใช้ `reduce` แทน spread เพื่อหลีกเลี่ยง stack overflow
Edge cases: ไม่มี argument, Infinity, และ NaN
`Math.min()` และ `Math.max()` มีพฤติกรรมพิเศษในบางกรณี: - **ไม่มี argument**: `Math.min()` คืน `Infinity`, `Math.max()` คืน `-Infinity` — ฟังดูแปลกแต่มีเหตุผล: ค่าเริ่มต้นต้องเป็นตัวที่ตัวไหนเทียบก็ชนะได้ - **NaN propagation**: ถ้ามี argument ตัวใดเป็น `NaN` ผลลัพธ์จะเป็น `NaN` เสมอ - **type coercion**: string ที่เป็นตัวเลขจะถูกแปลง, string ที่ไม่ใช่ตัวเลขจะกลายเป็น `NaN`
// ไม่มี argument
console.log(Math.min()); // Infinity ← ค่าเริ่มต้นสำหรับการหาน้อยสุด
console.log(Math.max()); // -Infinity ← ค่าเริ่มต้นสำหรับการหามากสุด
// NaN propagation
console.log(Math.min(1, 2, NaN)); // NaN ← มี NaN ผลลัพธ์เป็น NaN
console.log(Math.max(10, NaN, 5)); // NaN
// Type coercion
console.log(Math.min(1, "3", 2)); // 1 ← "3" ถูกแปลงเป็น 3
console.log(Math.max(1, "abc", 2)); // NaN ← "abc" แปลงไม่ได้
// มี argument ตัวเดียว
console.log(Math.min(5)); // 5
console.log(Math.max(5)); // 5- `Math.min()` ไม่มี argument → คืน `Infinity` (ค่าเริ่มต้นที่ตัวไหนเทียบก็น้อยกว่า)
- `Math.max()` ไม่มี argument → คืน `-Infinity` (ค่าเริ่มต้นที่ตัวไหนเทียบก็มากกว่า)
- ถ้ามี `NaN` ใน argument ตัวใด → ผลลัพธ์เป็น `NaN` เสมอ
- string ที่เป็นตัวเลขจะถูกแปลงเป็น number, string อื่น ๆ จะกลายเป็น `NaN`
การใช้จริง: จำกัดค่าในช่วง (Clamping)
**Clamping** คือการจำกัดค่าให้อยู่ในช่วงที่กำหนด ใช้ `Math.min` และ `Math.max` ร่วมกัน: ```javascript Math.max(min, Math.min(value, max)) ``` อธิบาย: 1. `Math.min(value, max)` — ตัดค่าที่เกิน max ลง 2. `Math.max(min, ...)` — ตัดค่าที่ต่ำกว่า min ขึ้น ผลลัพธ์: `value` จะอยู่ในช่วง **[min, max]** เสมอ ใช้จริง: slider, progress bar, score, page number, อุณหภูมิ
// Clamp คะแนนให้อยู่ในช่วง 0-100
function clampScore(score) {
return Math.max(0, Math.min(score, 100));
}
console.log(clampScore(85)); // 85 — อยู่ในช่วงแล้ว ไม่เปลี่ยน
console.log(clampScore(-5)); // 0 — ต่ำกว่า 0 → จับขึ้น 0
console.log(clampScore(150)); // 100 — เกิน 100 → ตัดลง 100// จำกัดเลขหน้าให้อยู่ในช่วง 1 ถึง totalPages
const totalPages = 10;
let currentPage = 15; // user พิมพ์เกิน
currentPage = Math.max(1, Math.min(currentPage, totalPages));
console.log(currentPage); // 10 — ไม่เกิน totalPages
currentPage = -3;
currentPage = Math.max(1, Math.min(currentPage, totalPages));
console.log(currentPage); // 1 — ไม่ต่ำกว่า 1- สูตร clamp: `Math.max(min, Math.min(value, max))` — จำกัดค่าในช่วง [min, max]
- `Math.min(value, max)` ตัดค่าที่เกิน, `Math.max(min, ...)` ตัดค่าที่ต่ำเกิน
- ใช้กับ: score (0-100), slider (0-1), page number (1-N), opacity (0-1)
- เป็น pattern ที่ใช้บ่อยในเกม, UI, และ form validation
เปรียบเทียบกับวิธีอื่นและสรุป
การหาค่าน้อยสุด/มากสุดจาก array สามารถทำได้หลายวิธี แต่ `Math.min/max` + spread เป็นวิธีที่กระชับและอ่านง่ายที่สุดสำหรับ array ขนาดปกติ
| วิธี | ตัวอย่าง | ข้อดี | ข้อควรระวัง |
|---|---|---|---|
| Math.min/max + spread | `Math.max(...arr)` | กระชับ อ่านง่าย | array ใหญ่มากอาจ stack overflow |
| array.reduce | `arr.reduce((a,b) => Math.max(a,b))` | ใช้กับ array ขนาดไหนก็ได้ | เขียนยาวกว่า |
| array.sort + index | `arr.sort((a,b) => b-a)[0]` | เรียงลำดับได้ด้วย | เปลี่ยน array เดิม (mutation) + ช้ากว่า |
- หาค่าน้อย/มากสุดจากตัวแปร 2-3 ตัว → `Math.min(a, b, c)` ตรง ๆ
- หาค่าน้อย/มากสุดจาก array ขนาดปกติ → `Math.max(...array)`
- หาค่าน้อย/มากสุดจาก array ขนาดใหญ่ → `array.reduce()`
- จำกัดค่าในช่วง → `Math.max(min, Math.min(value, max))`