คุณสมบัติ 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 ก่อนใช้งานครั้งใหม่