JavaScript
Array Methods
some
เรียนรู้ some() — method ตรวจสอบว่ามี element อย่างน้อย 1 ตัวที่ผ่านเงื่อนไข คืน boolean (true/false) หยุดทันทีเมื่อเจอตัวแรกที่ผ่าน โดยไม่เปลี่ยนต้นฉบับ ตั้งแต่ callback return true/false, short-circuit behavior, การใช้กับ array ของ object, ข้อผิดพลาดที่พบบ่อย ไปจนถึง some() vs find() vs includes() ผ่าน Lab 3 ข้อ
`some()` คืออะไร — ตรวจสอบว่ามี element อย่างน้อย 1 ตัวที่ผ่านเงื่อนไข
`some()` เป็น method ของ array ที่รับ callback function — เรียก callback ทีละตัวตามลำดับ element ใน array — ถ้า callback return `true` **อย่างน้อย 1 ตัว** → `some()` จะคืน `true` ทันที และหยุดตรวจสอบ element ที่เหลือ กฎสำคัญ: • `some()` จะคืน **boolean** — `true` หรือ `false` — ไม่ใช่ element, ไม่ใช่ index, ไม่ใช่ array • `some()` จะหยุดทันทีที่เจอ element แรกที่ callback return `true` — element ที่เหลือจะไม่ถูกเช็ก (short-circuit) — เหมือน `find()` • `some()` จะคืน `false` ถ้าไม่มี element ไหนเลยที่ callback return `true` — ไม่ error • `some()` จะคืน `false` ทันทีเมื่อเรียกใช้กับ **array ว่าง** — เพราะไม่มี element ให้เช็กเลย • `some()` ไม่เปลี่ยน array ต้นฉบับ (immutable method) ใช้ `some()` เมื่อคุณอยากรู้ว่า **"มี หรือ ไม่มี"** เท่านั้น — เช่น "มีสินค้าหมดสต็อกบ้างไหม", "มีคะแนนที่ผ่านเกณฑ์หรือไม่", "มี user ที่เป็น admin หรือเปล่า" — คุณไม่สนใจว่าคือใคร ตัวไหน หรือตำแหน่งอะไร — รู้แค่ "มี" หรือ "ไม่มี" ก็พอ
const nums = [1, 3, 5, 6, 7, 9];
// some() ตรวจสอบว่ามีเลขคู่อย่างน้อย 1 ตัวหรือไม่
const hasEven = nums.some(n => n % 2 === 0);
console.log(hasEven); // true ← boolean!
console.log(nums); // [1, 3, 5, 6, 7, 9] ← ต้นฉบับไม่เปลี่ยน ✓
สิ่งสำคัญที่ต้องรู้: • callback จะรับ element ทีละตัวตามลำดับ — `n` คือ element (1, 3, 5, 6, 7, 9) ตามลำดับ • `n % 2 === 0` — 1 → false → ไปต่อ, 3 → false → ไปต่อ, 5 → false → ไปต่อ, 6 → true → หยุด! • พอเจอ 6 → `some()` หยุดทันที — 7 และ 9 จะไม่ถูกเช็กเลย • ผลลัพธ์คือ `true` (boolean) — ไม่ใช่ element — ต่างจาก `find()` ที่คืนตัว element เอง • ถ้าไม่มีเลขคู่เลย → `some()` คืน `false` ลองดูความแตกต่างกับ `find()`: • `some(n => n % 2 === 0)` → `true` — "มีเลขคู่ไหม → มี" • `find(n => n % 2 === 0)` → `6` — "เลขคู่ตัวแรกคืออะไร → 6"
some() รับ element ทีละตัวตามลำดับ → ส่งให้ callback เช็ก true/false → เจอ true ตัวแรก → หยุด! คืน boolean true — ถ้าไม่มีเลย → คืน false
Callback ของ `some()` — element, index, array และการหยุดเมื่อเจอ
callback function ที่ส่งให้ `some()` รับ parameter ได้ 3 ตัว — เหมือน `map()`, `filter()`, `find()`, และ `findIndex()`: • **element** — ค่าของ element ปัจจุบัน (ใช้บ่อยที่สุด) • **index** — ตำแหน่ง index ของ element ปัจจุบัน • **array** — array ต้นฉบับทั้งหมด (ใช้น้อยมาก) จุดสำคัญของ `some()`: • **callback ต้อง return boolean** — `true` = "มีอย่างน้อย 1 ตัว" → หยุด!, `false` = "ยังไม่เจอ" → ไปต่อ • **ค่าที่ return ถูกแปลงเป็น boolean อัตโนมัติ** (truthy/falsy) — เหมือน `filter()` และ `find()` • **`some()` หยุดทันทีที่เจอ true** — เหมือน `find()` — ใช้ประโยชน์จาก short-circuit ได้ `some()` เหมาะกับคำถามแบบ "มี...ไหม" — เพราะคืน boolean ทำให้ใช้ใน `if` ได้ตรง ๆ โดยไม่ต้องเช็ก `!== undefined` เหมือน `find()`
const nums = [1, 3, 5, 2, 7, 9];
// ใช้ console.log ใน callback เพื่อดูว่า element ไหนถูกเช็กบ้าง
const hasEven = nums.some(n => {
console.log("เช็ก:", n);
return n % 2 === 0;
});
console.log("ผลลัพธ์:", hasEven);
// console แสดง:
// เช็ก: 1
// เช็ก: 3
// เช็ก: 5
// เช็ก: 2
// ผลลัพธ์: true
// จะเห็นว่า 7 และ 9 ไม่ถูกเช็ก! — some() หยุดที่ 2 (ตัวแรกที่ผ่าน)
const users = [
{ name: "สมชาย", role: "viewer" },
{ name: "สมหญิง", role: "editor" },
{ name: "สมศรี", role: "admin" },
];
// หาว่ามี admin ไหม — เช็กทีละ index
const hasAdmin = users.some((u, i) => {
console.log("เช็ก index:", i, "→", u.name);
return u.role === "admin";
});
console.log("มี admin:", hasAdmin);
// เช็ก index: 0 → สมชาย (viewer → false → ไปต่อ)
// เช็ก index: 1 → สมหญิง (editor → false → ไปต่อ)
// เช็ก index: 2 → สมศรี (admin → true → หยุด!)
// มี admin: true
เคล็ดลับ: `some()` ใช้คู่กับ `if` ได้สะอาดกว่า `find()` — เพราะ `find()` คืน `undefined` (falsy) หรือ object (truthy) — ต้องเช็กเพิ่มว่า "ไม่ใช่ undefined" — แต่ `some()` คืน boolean โดยตรง — `if (users.some(...))` อ่านง่าย ตรงไปตรงมา ```javascript if (users.some(u => u.role === "admin")) { console.log("มีคนที่สามารถจัดการระบบได้"); } else { console.log("ไม่มี admin — ทุกคนเป็นผู้ใช้ทั่วไป"); } ``` **จำง่าย ๆ:** `some()` = "มีบางตัวไหม" — ใช้เมื่อต้องการคำตอบ yes/no เท่านั้น
`some()` ในสถานการณ์จริง
`some()` เจอบ่อยมากในงานจริง — ทุกครั้งที่ต้องถามว่า "มี...หรือไม่": • ตรวจสอบว่ามีสินค้าหมดสต็อกหรือไม่ • ตรวจสอบว่ามี user ที่เป็น admin หรือไม่ • ตรวจสอบว่ามีคะแนนที่ต่ำกว่าเกณฑ์หรือไม่ • ตรวจสอบว่าฟอร์มมีช่องว่างหรือไม่ (validate form) • ตรวจสอบว่ามี element ที่ตรงเงื่อนไขอย่างน้อย 1 ตัวหรือไม่ ข้อดีของ `some()`: • คืน boolean → ใช้ใน `if` ได้ตรง ไม่งง • หยุดทันทีที่เจอ → เร็วกว่า `filter()` เมื่อแค่อยากรู้ว่ามีหรือไม่ • ชื่อ method สื่อความหมายชัด — "some" = "มีบางตัว" → อ่านแล้วเข้าใจเจตนาทันที
const products = [
{ name: "ปากกา", price: 25, inStock: true },
{ name: "สมุด", price: 45, inStock: false },
{ name: "ดินสอ", price: 10, inStock: true },
{ name: "ยางลบ", price: 15, inStock: true },
{ name: "ไม้บรรทัด", price: 30, inStock: true },
];
// ตรวจสอบ: มีสินค้าหมดสต็อกหรือไม่?
const hasOutOfStock = products.some(p => !p.inStock);
console.log(hasOutOfStock); // true — สมุดหมดสต็อก!
// ใช้ใน if — แสดงคำเตือนถ้ามีสินค้าหมด
if (hasOutOfStock) {
console.log("⚠️ มีสินค้าหมดสต็อก — กรุณาตรวจสอบคลัง");
}
// เปรียบเทียบกับ filter() — filter() ต้องนับหรือเช็ก length
const outOfStockItems = products.filter(p => !p.inStock);
console.log(outOfStockItems.length > 0); // true — ได้ผลเหมือนกัน แต่ verbose กว่า
// some() เร็วกว่า — หยุดที่ "สมุด" (ตัวที่ 2) filter() เช็กทั้ง 5 ตัว
const users = [
{ name: "สมชาย", role: "viewer", active: true },
{ name: "สมหญิง", role: "editor", active: false },
{ name: "สมศรี", role: "admin", active: true },
{ name: "สมบัติ", role: "viewer", active: true },
];
// ตรวจสอบ: มี admin หรือไม่?
const hasAdmin = users.some(u => u.role === "admin");
console.log("มี admin:", hasAdmin); // true
// ตรวจสอบ: มี user ที่ inactive หรือไม่?
const hasInactive = users.some(u => !u.active);
console.log("มี user inactive:", hasInactive); // true — สมหญิง inactive
// ตรวจสอบหลายเงื่อนไข — มี admin ที่ active หรือไม่? (ใช้ &&)
const hasActiveAdmin = users.some(u => u.role === "admin" && u.active);
console.log("มี active admin:", hasActiveAdmin); // true — สมศรี
ข้อผิดพลาดที่พบบ่อยเมื่อใช้ `some()`
- คิดว่า `some()` คืน element — `some()` คืน **boolean** (`true`/`false`) — ถ้าอยากได้ element ใช้ `find()` — `const user = users.some(u => u.role === 'admin')` → user = true (ไม่ใช่ object!) — ต้องใช้ `find()` แทน
- ลืม return ใน callback — `arr.some(n => { n > 3 })` — ไม่มี return → callback return `undefined` (falsy) → ไม่มีตัวไหนผ่านเลย → `some()` คืน `false` — แก้โดยใช้ shorthand `n => n > 3` หรือเติม `return`
- สับสน `some()` กับ `every()` — `some()` = มีอย่างน้อย 1 ตัว → check OR — `every()` = ทุกตัว → check AND — `[1, 2, 3].some(n => n > 2)` → true (3 > 2) — `[1, 2, 3].every(n => n > 2)` → false (1 ไม่ > 2)
- ใช้ `some()` เมื่ออยากได้ element — ถ้าอยากรู้ว่า "ใครคือ admin" → ใช้ `find()` — ถ้าอยากรู้ว่า "มี admin ไหม" → ใช้ `some()` — `some()` บอกแค่ว่ามีหรือไม่มี ไม่บอกว่าเป็นใคร
- ไม่ระวัง empty array — `[].some(n => n > 0)` → `false` เสมอ — เพราะไม่มี element ให้เช็กเลย — ตรงข้ามกับ `every()` ที่คืน `true` สำหรับ empty array — ระวังสับสน!
const users = [
{ name: "สมชาย", role: "viewer" },
{ name: "สมศรี", role: "admin" },
];
// ❌ ผิด — ใช้ some() แต่คาดหวัง object
const wrong = users.some(u => u.role === "admin");
console.log(wrong); // true ← boolean
console.log(wrong.name); // undefined — true ไม่ใช่ object!
// ❌ TypeError ตามมาถ้าใช้ .name ต่อ
// ✅ ถูก — ใช้ find() เพื่อหา object (อยากได้ตัว admin)
const admin = users.find(u => u.role === "admin");
console.log(admin.name); // สมศรี ✓
console.log(admin.role); // admin ✓
// ✅ ถูก — ใช้ some() เพื่อตรวจสอบว่ามีหรือไม่ (อยากได้ boolean)
if (users.some(u => u.role === "admin")) {
console.log("มี admin — แสดงหน้า admin panel ได้");
}
// empty array — some() คืน false เสมอ
const emptyArr = [];
console.log(emptyArr.some(n => n > 0)); // false — ไม่มี element ให้เช็ก
// เปรียบเทียบกับ every() — ระวัง! empty array → true
console.log(emptyArr.every(n => n > 0)); // true — "ทุกตัวผ่าน" เมื่อไม่มีตัวให้เช็ก
// some() กับเลขลบ
const nums1 = [0, -1, -2];
console.log(nums1.some(n => n > 0)); // false — ไม่มีตัวไหน > 0 เลย
// some() — มีอย่างน้อย 1 ตัว
const nums2 = [2];
console.log(nums2.some(n => n > 0)); // true — มี 1 ตัวที่ > 0
// some() — ใช้กับเงื่อนไขที่ไม่มีทางเป็นจริง
console.log([1, 2, 3].some(n => n > 100)); // false — ไม่มีตัวไหน > 100
`some()` vs `find()` vs `includes()` — เลือกใช้ให้เหมาะ
`some()`, `find()`, และ `includes()` ใช้ตรวจสอบ element ใน array ได้ — แต่เลือกใช้ต่างสถานการณ์: • **`some()`** — รับ callback → คืน **boolean** — "มี element ที่ตรงเงื่อนไขหรือไม่" • **`find()`** — รับ callback → คืน **element** (หรือ `undefined`) — "element ตัวแรกที่ตรงเงื่อนไขคืออะไร" • **`includes()`** — รับ **ค่า** โดยตรง → คืน **boolean** — "มีค่านี้ใน array หรือไม่" — ใช้ `===` เปรียบเทียบ กฎเลือกใช้: • อยากรู้ "มี/ไม่มี" ตามเงื่อนไข → `some()` — ยืดหยุ่น ใช้ callback ได้ • อยากได้ตัว element → `find()` — ได้ element มาใช้ต่อได้ • อยากรู้ "มีค่านี้เป๊ะ ๆ หรือไม่" → `includes()` — เร็วกว่าเมื่อไม่ต้องใช้ callback • `includes()` รับค่าโดยตรงเท่านั้น — ไม่รับ callback — ถ้าเงื่อนไขซับซ้อนต้องใช้ `some()` • `includes()` ใช้กับ array ของ object ไม่ได้ — เพราะ `===` เปรียบเทียบ reference — ใช้ `some()` แทน
| เรื่อง | some() | find() | includes() |
|---|---|---|---|
| คืนค่า | `true` / `false` (boolean) | element (หรือ `undefined`) | `true` / `false` (boolean) |
| รับอะไร | callback function | callback function | ค่าโดยตรง (ไม่ใช่ callback) |
| เปรียบเทียบ | custom ตาม callback | custom ตาม callback | `===` (strict equality) |
| ใช้กับ object array | ได้ ✓ — `arr.some(u => u.role === 'admin')` | ได้ ✓ — `arr.find(u => u.id === 5)` | ไม่ได้ — เปรียบเทียบ reference |
| หยุดเมื่อไหร่ | หยุดทันทีที่เจอ true | หยุดทันทีที่เจอ true | หยุดทันทีที่เจอ match |
| ไม่เจอ → คืน | `false` | `undefined` | `false` |
| เมื่อไหร่ควรใช้ | "มี...หรือไม่" — boolean check | "หา...ตัวแรก" — get element | "มีค่านี้เป๊ะ ๆ หรือไม่" — value check |
const nums = [1, 3, 5, 6, 7];
// === some() — มีเลขคู่หรือไม่ → boolean
const hasEven = nums.some(n => n % 2 === 0);
console.log(hasEven); // true — "มีเลขคู่"
// === find() — เลขคู่ตัวแรกคืออะไร → element
const firstEven = nums.find(n => n % 2 === 0);
console.log(firstEven); // 6 — "เลขคู่ตัวแรก"
// === includes() — มี 5 อยู่ใน array หรือไม่ → boolean
const hasFive = nums.includes(5);
console.log(hasFive); // true — "มี 5"
// === includes() ใช้กับ object ไม่ได้ — เพราะ === เปรียบเทียบ reference
const users = [{ name: "สมชาย" }, { name: "สมศรี" }];
console.log(users.includes({ name: "สมชาย" })); // false — คนละ reference!
// ต้องใช้ some() กับ array ของ object
console.log(users.some(u => u.name === "สมชาย")); // true ✓
// เปรียบเทียบ speed — some() หยุดเร็วกว่า filter() สำหรับ boolean check
const scores = [45, 82, 67, 91, 55];
// แค่อยากรู้ว่ามีคะแนน >= 80 ไหม
console.log(scores.some(s => s >= 80)); // true — หยุดที่ 82 (index 1)
// เทียบกับ filter() — เช็กทั้ง 5 ตัว
console.log(scores.filter(s => s >= 80).length > 0); // true — แต่ช้ากว่า
เคล็ดลับ: • "มีเลขคู่ใน array หรือไม่" → `some()` — เพราะใช้ callback กำหนดเงื่อนไขเองได้ • "เลขคู่ตัวแรกคืออะไร" → `find()` — เพราะอยากได้ค่ามาใช้ต่อ • "มีเลข 5 ใน array หรือไม่" → `includes()` — เพราะรู้ค่าเป๊ะ ๆ ไม่ต้องใช้ callback • **หลีกเลี่ยง `arr.find(...) !== undefined` เพื่อตรวจสอบว่ามีหรือไม่** — ใช้ `arr.some(...)` แทน — เพราะ `some()` สื่อเจตนาชัดกว่าและสั้นกว่า — "อยากรู้ว่ามีหรือไม่" • **หลีกเลี่ยง `arr.filter(...).length > 0` เพื่อตรวจสอบว่ามีหรือไม่** — ใช้ `arr.some(...)` แทน — เพราะ `some()` หยุดที่ตัวแรกที่เจอ — `filter()` ต้องเช็กทั้ง array เสมอ