Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

คุณสมบัติ lastIndex ใน JavaScript Regular Expression

คุณสมบัติ lastIndex ของออบเจ็กต์ RegExp ใช้เก็บตำแหน่งดัชนี (Index) ที่จะเริ่มค้นหาครั้งต่อไป ทำงานเฉพาะเมื่อตั้งค่า Flag g (Global) เท่านั้น

ลักษณะการทำงาน

  • เริ่มต้นที่ 0
  • หลังจาก test() หรือ exec() พบค่าตรง → อัปเดตเป็นตำแหน่งหลังค่าที่พบ
  • ถ้าไม่พบ → รีเซ็ตกลับเป็น 0
  • สามารถกำหนดค่าเองได้ เพื่อควบคุมตำแหน่งเริ่มต้นการค้นหา

ตัวอย่าง: ติดตามตำแหน่งการค้นหา "ing"

<!DOCTYPE html>
<html lang="th">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RegExp lastIndex</title>
    <style>
        body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; }
        .sample, .result { font-size: 18px; font-weight: 500; color: red; }
        button { padding: 8px 16px; margin: 10px 0; cursor: pointer; }
    </style>
</head>
<body>
    <h1>คุณสมบัติ lastIndex ใน JavaScript</h1>
    <div class="sample">The king bought an expensive ring.</div>
    <div style="font-weight: bold; color: black;" class="result"></div>
    <button class="Btn">ค้นหา "ing" ถัดไป</button>
    <h3>กดปุ่มเพื่อหาตำแหน่งของ "ing" ในประโยคข้างต้น</h3>

    <script>
        let sampleEle = document.querySelector(".sample");
        let resultEle = document.querySelector(".result");
        
        // สร้าง RegExp ด้วย Flag g
        let regex = new RegExp("ing", "g");
        
        // เรียก test() ครั้งแรกเพื่อเริ่มการค้นหา
        regex.test(sampleEle.innerHTML);
        
        document.querySelector(".Btn").addEventListener("click", () => {
            resultEle.innerHTML += `🔍 "ing" พบที่ Index = ${regex.lastIndex} <br>`;
            // เรียก test() อีกครั้งเพื่อค้นหาตัวถัดไป
            regex.test(sampleEle.innerHTML);
        });
    </script>
</body>
</html>

ผลลัพธ์

ประโยค: "The king bought an expensive ring."
กดปุ่มครั้งที่ 1: "ing" พบที่ Index = 11 (คำว่า "king")
กดปุ่มครั้งที่ 2: "ing" พบที่ Index = 31 (คำว่า "ring")
กดปุ่มครั้งที่ 3: "ing" พบที่ Index = 0 (ไม่พบ รีเซ็ตกลับ 0)

การประยุกต์ใช้: Iterator แบบกำหนดเอง

function* findAllMatches(str, regex) {
    // ต้องใช้ regex ใหม่หรือ clone เพื่อไม่ให้ lastIndex ชนกัน
    const localRegex = new RegExp(regex.source, regex.flags);
    let match;
    
    while ((match = localRegex.exec(str)) !== null) {
        yield {
            value: match[0],
            index: match.index,
            groups: match.groups
        };
    }
}

// ใช้งาน
const text = "cat bat rat";
for (const match of findAllMatches(text, /(\w+)at/g)) {
    console.log(`${match.value} at index ${match.index}`);
}
// cat at index 0
// bat at index 4
// rat at index 8

ข้อควรระวัง

  • lastIndex เป็น Shared State - ถ้าใช้ RegExp เดียวกันหลายที่ lastIndex จะชนกัน
  • ควรสร้าง RegExp ใหม่ทุกครั้ง หรือใช้ matchAll() แทน (ปลอดภัยกว่า)
  • Flag y (Sticky) ทำงานคล้ายกันแต่ต้องตรงตำแหน่ง lastIndex ทุกประการ

ตัวอย่างปัญหา lastIndex ชนกัน

const regex = /foo/g;
const str1 = "foo bar";
const str2 = "foo baz";

regex.test(str1); // true, lastIndex = 3
regex.test(str2); // false! เพราะเริ่มค้นหาที่ index 3 ของ str2 (คือ " baz")

แก้ไข: ใช้ new RegExp(regex) หรือ regex.lastIndex = 0 ก่อนใช้งานครั้งใหม่