JavaScript
Array Methods
find
เรียนรู้ find() — method หา element ตัวแรกที่ตรงเงื่อนไขและหยุดทันที คืน element เดียว (หรือ undefined ถ้าไม่เจอ) โดยไม่เปลี่ยนต้นฉบับ ตั้งแต่ callback return true/false, การหา object จาก id, การจัดการ undefined, ข้อผิดพลาดที่พบบ่อย ไปจนถึง find() vs filter() ผ่าน Lab 3 ข้อ
`find()` คืออะไร — หา element ตัวแรกที่ตรงเงื่อนไข
`find()` เป็น method ของ array ที่รับ callback function — เรียก callback ทีละตัวตามลำดับ element ใน array **จนกว่า** callback จะ return `true` — แล้วคืน (return) **element ตัวนั้น** ทันที โดยไม่เช็ก element ที่เหลือต่อ กฎสำคัญ: • `find()` จะคืน **element เดียว** — ไม่ใช่ array — ต่างจาก `filter()` ที่คืน array • `find()` จะหยุดทันทีที่เจอ element แรกที่ callback return `true` — element ที่เหลือจะไม่ถูกเช็ก • `find()` จะคืน `undefined` ถ้าไม่มี element ไหนเลยที่ callback return `true` — ไม่ error • `find()` ไม่เปลี่ยน array ต้นฉบับ (immutable method) ใช้ `find()` เมื่อคุณอยากหา element **ตัวแรก** ที่ตรงตามเงื่อนไข — เช่น หา user จาก id, หาสินค้าตัวแรกที่มีในสต็อก, หรือหาคะแนนแรกที่ผ่านเกณฑ์
const nums = [1, 3, 2, 5, 4];
// find() รับ arrow function — หยุดที่ element แรกที่ callback return true
const firstEven = nums.find(n => n % 2 === 0);
console.log(firstEven); // 2 ← element เดียว ไม่ใช่ array!
console.log(nums); // [1, 3, 2, 5, 4] ← ต้นฉบับไม่เปลี่ยน ✓
สิ่งสำคัญที่ต้องรู้: • callback จะรับ element ทีละตัวตามลำดับ — `n` คือ element (1, 3, 2, 5, 4) ตามลำดับ • callback ต้อง return boolean — `n % 2 === 0` คืน `true` สำหรับ 2 (เลขคู่ตัวแรก) • พอเจอ 2 → `find()` หยุดทันที — 5 และ 4 จะไม่ถูกเช็กเลย • ผลลัพธ์คือ `2` (element เอง) — ไม่ใช่ `[2]` (array) — ต่างจาก `filter()` อย่างชัดเจน • ถ้าไม่มีเลขคู่เลย → `find()` คืน `undefined`
find() รับ element ทีละตัวตามลำดับ → ส่งให้ callback เช็ก true/false → เจอ true ตัวแรก → หยุด! คืน element ตัวนั้น — ถ้าไม่มีเลย → คืน undefined
Callback function ของ `find()` — element, index, array
callback function ที่ส่งให้ `find()` รับ parameter ได้ 3 ตัว — เหมือน `map()` และ `filter()`: • **element** — ค่าของ element ปัจจุบัน (ใช้บ่อยที่สุด) • **index** — ตำแหน่ง index ของ element ปัจจุบัน • **array** — array ต้นฉบับทั้งหมด (ใช้น้อยมาก) จุดสำคัญของ `find()`: • **callback ต้อง return boolean** — `true` = หยุดและคืน element นี้, `false` = ไปต่อ • **ค่าที่ return ถูกแปลงเป็น boolean อัตโนมัติ** (truthy/falsy) — เหมือน `filter()` • ถ้า callback return `true` → `find()` หยุดทันทีด้วย element ตัวนั้น • ถ้า callback return `false` ทุกตัว → `find()` คืน `undefined`
const users = [
{ id: 1, name: "สมชาย", role: "admin" },
{ id: 2, name: "สมหญิง", role: "editor" },
{ id: 3, name: "สมศรี", role: "viewer" },
];
// หา user ที่ id === 2 — ใช้บ่อยมากในงานจริง
const user = users.find(u => u.id === 2);
console.log(user); // { id: 2, name: 'สมหญิง', role: 'editor' }
// เป็น object — ไม่ใช่ array!
// หา admin คนแรก
const admin = users.find(u => u.role === "admin");
console.log(admin); // { id: 1, name: 'สมชาย', role: 'admin' }
const scores = [45, 82, 67, 91, 55];
// หา element ตัวแรกที่มี index >= 3 และ score > 50
// ใช้ callback รับทั้ง element และ index
const result = scores.find((s, i) => i >= 3 && s > 50);
console.log(result); // 91
// index 3: 91 → i >= 3? ✓, s > 50? ✓ → หยุด! คืน 91
// index 4: ไม่ถูกเช็ก
เคล็ดลับ: ในงานจริง `find()` ถูกใช้บ่อยที่สุดเพื่อหา object จาก id — `arr.find(item => item.id === targetId)` — เพราะมี `id` เป็นค่าที่ไม่ซ้ำกันแน่นอน ใช้ `index` เมื่อต้องการเช็กแค่บางตำแหน่ง — เช่น หา element ตั้งแต่ตำแหน่งที่ 3 ขึ้นไป — หรือหา element ตามลำดับที่ต้องการ
`find()` ในสถานการณ์จริง
`find()` เจอบ่อยมากในงานจริง — ทุกครั้งที่ต้องหาข้อมูลหนึ่งชิ้นจาก array: • หา object จาก id (user, product, order) • หาสินค้าตัวแรกที่ยังมีในสต็อก • หาคะแนนแรกที่ผ่านเกณฑ์ • ตรวจสอบว่ามี element ที่ตรงเงื่อนไขหรือไม่ (ใช้ `if (result)` หลัง `find()`) • หาค่าแรกในช่วงที่ต้องการ ข้อดีของ `find()` เหนือ `filter()`: คืน element เดียว — ไม่ต้องใช้ `[0]` ต่อท้าย — และหยุดทันที ไม่ต้องเช็กทั้ง array
const products = [
{ id: 1, name: "ปากกา", price: 25, inStock: true },
{ id: 2, name: "สมุด", price: 45, inStock: false },
{ id: 3, name: "ดินสอ", price: 10, inStock: true },
{ id: 4, name: "ยางลบ", price: 15, inStock: true },
];
// หาสินค้าตัวแรกที่ inStock === true
const firstAvailable = products.find(p => p.inStock);
console.log(firstAvailable);
// { id: 1, name: 'ปากกา', price: 25, inStock: true }
// หาสินค้าตามชื่อ — ระวัง: ถ้าไม่มี → undefined!
const notebook = products.find(p => p.name === "สมุด");
console.log(notebook); // { id: 2, name: 'สมุด', price: 45, inStock: false }
const unknownItem = products.find(p => p.name === "กระเป๋า");
console.log(unknownItem); // undefined — ไม่มีสินค้าชื่อนี้!
const scores = [45, 82, 67, 91, 55, 78];
// หาคะแนนตัวแรกที่ >= 80
const highScore = scores.find(s => s >= 80);
console.log(highScore); // 82
// ใช้ผลลัพธ์ต่อเลย — ระวัง undefined!
if (highScore !== undefined) {
console.log("คะแนนสูงสุดตัวแรกที่ผ่านเกณฑ์คือ " + highScore);
// คะแนนสูงสุดตัวแรกที่ผ่านเกณฑ์คือ 82
} else {
console.log("ไม่มีคะแนนที่ผ่านเกณฑ์");
}
// === วิธีสั้น: ใช้ truthy check (undefined = falsy)
const firstPassing = scores.find(s => s >= 60);
if (firstPassing) {
console.log("มีคนผ่าน: " + firstPassing); // มีคนผ่าน: 82
}
ข้อผิดพลาดที่พบบ่อยเมื่อใช้ `find()`
- คิดว่า `find()` คืน array — `find()` คืน **element เดียว** — ถ้าอยากได้ array ใช้ `filter()` — `const first = arr.filter(f).find(...)` ไม่ถูก — ใช้ `arr.find(...)` โดยตรง
- ลืม return ใน callback — `arr.find(n => { n > 3 })` — ไม่มี return → callback return `undefined` (falsy) → ไม่มีตัวไหนผ่านเลย → `find()` คืน `undefined` — แก้โดยใช้ shorthand `n => n > 3` หรือเติม `return`
- ไม่ตรวจสอบ `undefined` — `find()` คืน `undefined` เมื่อหาไม่เจอ — ถ้าใช้ผลลัพธ์ต่อโดยไม่เช็ก จะเกิด error — `const user = arr.find(...); console.log(user.name)` → TypeError ถ้า `user` เป็น `undefined`
- คิดว่า `find()` คืนทุกตัวที่ตรงเงื่อนไข — `find()` คืนแค่ **ตัวแรก** — ถ้าอยากได้ทุกตัวที่ตรงเงื่อนไข ใช้ `filter()` — `arr.filter(n => n > 5)`
- คิดว่า `find()` หยุดเมื่อเจอ false — `find()` หยุดเมื่อเจอ **true** — ถ้า return false → ไปต่อ — return true → หยุดทันที
const nums = [1, 2, 3, 4, 5];
// ❌ ผิด — ลืม return ใน callback แบบ { }
const wrong1 = nums.find(n => {
n > 3; // ← ไม่มี return!
});
console.log(wrong1); // undefined — callback return undefined (falsy) → ไม่มีตัวไหนผ่าน
// ✅ ถูก — ใช้ shorthand (ไม่มี { })
const correct1 = nums.find(n => n > 3);
console.log(correct1); // 4
// ❌ ผิด — ไม่ตรวจสอบ undefined ก่อนใช้ต่อ
const wrong2 = nums.find(n => n > 10);
console.log(wrong2.value); // TypeError: Cannot read properties of undefined
// ✅ ถูก — ตรวจสอบก่อนใช้
const found = nums.find(n => n > 10);
if (found) {
console.log("เจอแล้ว");
} else {
console.log("ไม่มีตัวที่ > 10");
// ไม่มีตัวที่ > 10
}
const nums = [1, 2, 3, 4, 5];
// ❌ เข้าใจผิด — คิดว่า find() คืน array
const wrong = nums.find(n => n > 3);
console.log(wrong.length); // undefined — เพราะ wrong คือ 4 (number) ไม่ใช่ array!
// ✅ find() คืน element เดียว — เข้าถึง element โดยตรงได้เลย
const first = nums.find(n => n > 3);
console.log(first); // 4 — number
// ✅ filter() คืน array — ต้องใช้ [0] ถ้าอยากได้ element
const filtered = nums.filter(n => n > 3);
console.log(filtered); // [4, 5] — array
console.log(filtered[0]); // 4 — element ตัวแรก
// ✅ ถ้าอยากได้แค่ element ตัวเดียว — ใช้ find() ไม่ใช่ filter()[0]
const better = nums.find(n => n > 3);
console.log(better === filtered[0]); // true — ผลลัพธ์เหมือนกัน แต่ find() ดีกว่า
`find()` vs `filter()` — เลือกใช้ให้เหมาะ
`find()` และ `filter()` ใช้หา element ใน array ได้ทั้งคู่ — แต่คืนค่าต่างกัน: • `find()` — หา **element ตัวแรก** ที่ตรงเงื่อนไข → คืน **element** (หรือ `undefined`) • `filter()` — หา **ทุก element** ที่ตรงเงื่อนไข → คืน **array ใหม่** (หรือ `[]`) กฎง่าย ๆ: • อยากได้ element ตัวเดียว → ใช้ `find()` • อยากได้หลาย element ที่ผ่านเงื่อนไข → ใช้ `filter()` • `find()` หยุดที่ตัวแรก → เร็วกว่าเมื่อ array ใหญ่ → ไม่ต้องเช็กทั้ง array • `filter()` ต้องเช็กทุกตัวเสมอ
| เรื่อง | find() | filter() |
|---|---|---|
| คืนค่า | element เดียว (หรือ undefined) | array ใหม่ (หรือ []) |
| หยุดเมื่อไหร่ | หยุดทันทีที่เจอตัวแรกที่ผ่าน | เช็กทุกตัวเสมอ |
| จำนวนบรรทัด | 1–2 บรรทัด | 1–2 บรรทัด |
| ไม่เปลี่ยนต้นฉบับ | ไม่เปลี่ยน ✓ | ไม่เปลี่ยน ✓ |
| เมื่อเจอตัวที่ต้องการหลายตัว | คืนแค่ตัวแรก — ตัวที่เหลือถูกละเลย | คืนทุกตัวที่ผ่าน — ครบถ้วน |
| เมื่อไม่มีตัวไหนผ่านเลย | undefined | [] (array ว่าง) |
| เมื่อไหร่ควรใช้ | หา element ตัวแรกที่ตรงเงื่อนไข — หา id, หาสินค้าตัวแรก, หาคะแนนแรกที่ผ่าน | กรอง element ทุกตัวที่ตรงเงื่อนไข — รายการสินค้าในสต็อก, คะแนนที่ผ่านทั้งหมด, ชื่อที่ขึ้นต้นด้วยตัวอักษรหนึ่ง |
const scores = [45, 82, 67, 91, 55, 78];
// === find() — หาคะแนนตัวแรกที่ >= 60
const firstPassing = scores.find(s => s >= 60);
console.log(firstPassing); // 82 — element เดียว
// === filter() — หาคะแนนทุกตัวที่ >= 60
const allPassing = scores.filter(s => s >= 60);
console.log(allPassing); // [82, 67, 91, 78] — array
// === find() กับ object — หา user คนแรกที่ role === "admin"
const users = [
{ name: "สมชาย", role: "viewer" },
{ name: "สมหญิง", role: "admin" },
{ name: "สมศรี", role: "admin" },
];
const admin = users.find(u => u.role === "admin");
console.log(admin); // { name: 'สมหญิง', role: 'admin' } — แค่คนแรก!
const allAdmins = users.filter(u => u.role === "admin");
console.log(allAdmins);
// [{ name: 'สมหญิง', role: 'admin' }, { name: 'สมศรี', role: 'admin' }]
// — ทุกคนที่เป็น admin
เคล็ดลับ: • โจทย์ "หา user id = 5" → `find()` — เพราะ id ไม่ซ้ำ ผลลัพธ์มีตัวเดียวแน่นอน • โจทย์ "หาสินค้าทั้งหมดที่ inStock" → `filter()` — เพราะอาจมีหลายตัว • โจทย์ "มีสินค้าในสต็อกบ้างไหม" → `find()` + `if (result)` — เพราะแค่อยากรู้ว่ามีหรือไม่ • หลีกเลี่ยง `filter(...)[0]` — ใช้ `find()` แทน — เพราะ `filter()` เปลือง (เช็กทั้ง array) และอ่านเจตนาไม่ชัด