JavaScript
Arrays
indexOf
เรียนรู้ indexOf() — method ค้นหาตำแหน่ง element ใน Array ตั้งแต่การหาค่า index แรกที่เจอ, ค่า return -1 เมื่อไม่เจอ, การใช้ fromIndex ควบคุมจุดเริ่มค้น, พฤติกรรม Strict Equality (===) ที่ส่งผลต่อการค้นหา NaN และ object, ไปจนถึงการนำไปใช้ตรวจสอบว่า element มีอยู่ใน array หรือไม่ ผ่าน Lab 3 ข้อ
`indexOf()` คืออะไร — ค้นหาตำแหน่งของ element ใน Array
indexOf() เป็น method ใน array ใช้ค้นหาว่า element ที่เราต้องการอยู่ที่ตำแหน่ง (index) ใดใน array สิ่งที่ต้องรู้: • คืนค่า (return) เป็น index แรกที่เจอ (number) • ถ้าไม่เจอ element นั้นเลย — คืนค่า -1 • ค้นหาจากซ้ายไปขวา (index 0 → index สุดท้าย) • ใช้ Strict Equality (===) ในการเปรียบเทียบ • รับ parameter ได้ 2 ตัว: searchElement (จำเป็น) และ fromIndex (ไม่จำเป็น)
const fruits = ["แอปเปิ้ล", "กล้วย", "ส้ม", "กล้วย"];
// index: 0 1 2 3
const pos = fruits.indexOf("กล้วย");
console.log(pos); // 1 ← index แรกที่เจอ "กล้วย" คือ 1
// ไม่ใช่ 3 เพราะหยุดที่ตัวแรกที่เจอ
const notFound = fruits.indexOf("มะม่วง");
console.log(notFound); // -1 ← ไม่มี "มะม่วง" ใน arrayจากตัวอย่าง: indexOf("กล้วย") คืนค่า 1 — เพราะเจอ "กล้วย" ครั้งแรกที่ index 1 แล้วหยุดทันที ไม่ค้นต่อไปที่ index 3 ส่วน indexOf("มะม่วง") คืนค่า -1 — เพราะไม่มี element นี้อยู่ใน array เลย กฎสำคัญ: indexOf คืนค่า index แรกเสมอ และ -1 แปลว่าไม่มี element นั้น
const roles = ["admin", "editor", "viewer"];
// index: 0 1 2
const pos = roles.indexOf("admin");
if (pos !== -1) {
console.log("admin อยู่ที่ index", pos); // admin อยู่ที่ index 0
}
// === เปรียบเทียบ: indexOf("guest") === -1 คือไม่มี
if (roles.indexOf("guest") === -1) {
console.log('ไม่มี "guest" ใน array'); // ข้อความนี้จะถูกแสดง
}รูปแบบการใช้งานที่พบบ่อย: ใช้ indexOf() !== -1 เพื่อตรวจสอบว่า element มีอยู่ใน array หรือไม่ — ในบทถัดไปเราจะได้เรียน includes() ซึ่งทำให้โค้ดสั้นลงอีก แต่วิธีนี้เป็นพื้นฐานสำคัญและถูกใช้ในโค้ด JavaScript มานานแล้ว
เริ่มค้นจากตำแหน่งที่กำหนดด้วย `fromIndex`
indexOf() รับ parameter ตัวที่สองชื่อ fromIndex — ใช้กำหนดว่าจะเริ่มค้นจาก index ใด ค่าเริ่มต้น (default) คือ 0 — เริ่มค้นจากตัวแรกสุด ถ้าไม่ระบุ fromIndex ประโยชน์ของ fromIndex: • ค้นหา occurrence ที่ 2, 3, ... ของ element เดิม • ข้าม element ช่วงแรกที่เราไม่สนใจ • เร่งความเร็วเมื่อรู้ว่าข้อมูลที่ต้องการอยู่ท้าย ๆ
const items = ["A", "B", "A", "C", "A"];
// index: 0 1 2 3 4
// ไม่ระบุ fromIndex — เริ่มจาก 0 (default)
console.log(items.indexOf("A")); // 0 ← เจอ "A" ตัวแรกที่ index 0
// fromIndex = 1 — เริ่มค้นจาก index 1 (ข้าม index 0)
console.log(items.indexOf("A", 1)); // 2 ← เจอ "A" ตัวที่สองที่ index 2
// fromIndex = 3 — เริ่มค้นจาก index 3
console.log(items.indexOf("A", 3)); // 4 ← เจอ "A" ตัวที่สามที่ index 4
// fromIndex = 5 — เริ่มค้นจาก index 5 (เกิน length → ไม่เจอ)
console.log(items.indexOf("A", 5)); // -1 ← จาก index 5 เป็นต้นไปไม่มี "A"ข้อควรรู้เกี่ยวกับ fromIndex: • ถ้า fromIndex >= length → indexOf return -1 ทันที (ไม่ค้นเลย) • ถ้า fromIndex < 0 → indexOf นับจากท้าย array เช่น -1 = ตัวสุดท้าย, -2 = ตัวรองสุดท้าย • ทิศทางการค้นหายังเป็นซ้าย→ขวาเหมือนเดิม — fromIndex แค่เปลี่ยนจุดเริ่ม ไม่ได้เปลี่ยนทิศทาง
const chars = ["X", "Y", "Z", "Y", "W"];
// index: 0 1 2 3 4
// จากท้าย: -5 -4 -3 -2 -1
// fromIndex = -1 → เริ่มที่ index 4 (ตัวสุดท้าย)
console.log(chars.indexOf("Y", -1)); // -1 ← จาก index 4 ไปทางขวาไม่มี "Y"
// fromIndex = -2 → เริ่มที่ index 3
console.log(chars.indexOf("Y", -2)); // 3 ← เจอ "Y" ที่ index 3
// fromIndex = -4 → เริ่มที่ index 1
console.log(chars.indexOf("Y", -4)); // 1 ← เจอ "Y" ตัวแรกที่ index 1
// fromIndex = -100 → น้อยเกินไป → เริ่มที่ 0
console.log(chars.indexOf("Y", -100)); // 1 ← เท่ากับ indexOf("Y", 0)เวลาจำให้คิดง่าย ๆ: • fromIndex >= 0 → เริ่มค้นตรง index นั้นเลย • fromIndex < 0 → เอา length + fromIndex เป็นจุดเริ่ม (จากท้ายนับมา) เช่น fromIndex = -1 → length + (-1) = index 4 • ถ้าผลลัพธ์ < 0 (fromIndex ติดลบมาก ๆ) → เริ่มที่ 0 ทิศทางค้นหายังเป็นซ้ายไปขวาในทุกกรณี
`indexOf()` ใช้ `===` ในการเปรียบเทียบ — ผลกระทบที่ต้องรู้
indexOf() ใช้ Strict Equality (===) เปรียบเทียบค่ากับ element ใน array — ไม่ใช้การแปลง type เหมือน Loose Equality (==) นี่คือประเด็นสำคัญเพราะมีผลต่อพฤติกรรมหลายอย่าง: • ตัวพิมพ์เล็ก/ใหญ่ของ string เป็นคนละค่ากัน ("A" !== "a") • number กับ string ที่หน้าตาเหมือนกันเป็นคนละ type (1 !== "1") • ไม่สามารถใช้ indexOf หา NaN ได้ — เพราะ NaN !== NaN เสมอ • ไม่สามารถใช้ indexOf หา object/array ด้วยค่าเท่ากันได้ — เพราะ === เปรียบเทียบ reference
| searchElement | element ใน array | indexOf เจอ? | เพราะว่า |
|---|---|---|---|
| "hello" | "hello" | เจอ (=== เปรียบเทียบค่าเท่ากัน) | string เหมือนกันทั้งค่าและ type |
| "Hello" | "hello" | ไม่เจอ — คืน -1 | "H" !== "h" — ตัวพิมพ์เล็กใหญ่ต่างกัน |
| 42 | 42 | เจอ | number เหมือนกันทั้งค่าและ type |
| "42" | 42 | ไม่เจอ — คืน -1 | "42" (string) !== 42 (number) — type ต่างกัน |
| NaN | NaN | ไม่เจอ — คืน -1 | NaN !== NaN — เป็นกฎของ JavaScript |
| true | true | เจอ (=== เปรียบเทียบค่าเท่ากัน) | boolean เหมือนกัน |
| null | null | เจอ | null === null |
| undefined | undefined | เจอ | undefined === undefined |
const mixed = [1, "1", "hello", "Hello"];
// index: 0 1 2 3
console.log(mixed.indexOf(1)); // 0 — number 1
console.log(mixed.indexOf("1")); // 1 — string "1" คนละ type กับ 1
console.log(mixed.indexOf("hello")); // 2 — ตัวพิมพ์เล็ก
console.log(mixed.indexOf("Hello")); // 3 — ตัว H ใหญ่ ≠ h เล็กข้อควรรู้เพิ่มเติม: indexOf() ไม่สามารถใช้หา object หรือ array ด้วยการเทียบค่าได้ — เพราะ === กับ object/array ดูที่ reference (ตำแหน่งในหน่วยความจำ) ไม่ใช่ดูว่า properties ข้างในเท่ากันหรือไม่ ถ้าต้องการหาว่ามี object ที่มี properties ตามที่ต้องการหรือไม่ — ต้องใช้ findIndex() หรือ find() (จะเรียนในบท array methods)
// NaN — indexOf เจอไม่ได้เลย
const nums = [NaN, 1, 2];
console.log(nums.indexOf(NaN)); // -1 ← NaN !== NaN เสมอ
// Object — เทียบ reference ไม่เท่ากันแม้ properties เหมือน
const people = [{ name: "สมชาย" }, { name: "สมศรี" }];
console.log(people.indexOf({ name: "สมชาย" })); // -1 ← คนละ referenceจุดที่มือใหม่มักพลาด
- indexOf() return index ไม่ใช่ boolean — มือใหม่มักเขียน if (arr.indexOf(x)) {...} ซึ่งผิด เพราะ index 0 เป็น falsy (จะถูกมองเป็น false) — ต้องใช้ if (arr.indexOf(x) !== -1) เสมอ
- indexOf() หยุดที่ตัวแรกที่เจอ — ไม่ได้คืนค่าทุก index ที่เจอ ถ้าต้องการรู้ทุกตำแหน่งต้องใช้ loop หรือ method อื่น
- indexOf() ใช้ === ในการเปรียบเทียบ — "5" กับ 5 ถือเป็นคนละตัว เหมือนที่เราเรียนในบท comparison operators
- fromIndex ไม่เปลี่ยนทิศทางการค้น — ถึงแม้ fromIndex จะติดลบ indexOf ก็ยังค้นจากซ้ายไปขวาอยู่ดี ไม่ได้ค้นย้อนกลับ
- indexOf() หา NaN ไม่ได้ — เพราะ NaN === NaN เป็น false ถ้าต้องการตรวจสอบว่า array มี NaN หรือไม่ ต้องใช้ findIndex() หรือ includes() (includes() ใช้ SameValueZero ซึ่งหา NaN ได้)
- indexOf() หา object/array ไม่ได้ด้วยการเทียบค่า — เพราะ === เทียบ reference ถ้าต้องการหา object ต้องใช้ findIndex()
- indexOf() ใช้กับ array เท่านั้น — ไม่ใช่ string method (string มี indexOf() เช่นกัน แต่เป็นคนละ method กับของ array — จะเรียนในบท string methods)