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

JavaScript RegExp toString() Method - แปลง Regular Expression เป็น String


RegExp.prototype.toString() คืออะไร?

คืนค่า String representation ของ Regular Expression object ในรูปแบบ Literal notation: /pattern/flags

  • ใช้สำหรับ Debugging, Logging, Display pattern ให้ผู้ใช้เห็น
  • คืนค่า string ที่เป็น valid RegExp literal เสมอ
  • Escape special characters อัตโนมัติ

ตัวอย่างโค้ดครบถ้วน

<!DOCTYPE html>
<html lang="th">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>RegExp toString() Demo</title>
  <style>
    body { font-family: 'Segoe UI', sans-serif; padding: 20px; max-width: 800px; margin: 0 auto; }
    .panel { background: #f5f5f5; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
    .code { background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 4px; font-family: monospace; overflow-x: auto; }
    .output { background: #e8f5e9; padding: 15px; border-radius: 4px; font-family: monospace; white-space: pre-wrap; }
    button { padding: 10px 20px; background: #7e32d4; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 10px; margin-bottom: 10px; }
    button:hover { background: #6a1b9a; }
    table { width: 100%; border-collapse: collapse; margin-top: 10px; }
    th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
    th { background: #7e32d4; color: white; }
    .regex-display { font-family: monospace; background: #fff3e0; padding: 2px 6px; border-radius: 3px; }
  </style>
</head>
<body>
  <h1>RegExp.prototype.toString()</h1>
  <p>แปลง Regular Expression object เป็น String literal format</p>
  
  <div class="panel">
    <h3>ทดสอบ RegExp ต่างๆ</h3>
    <button onclick="testBasic()">Basic Patterns</button>
    <button onclick="testFlags()">Flags (g, i, m, s, u, y)</button>
    <button onclick="testSpecialChars()">Special Characters</button>
    <button onclick="testConstructors()">Constructor vs Literal</button>
  </div>
  
  <div class="panel">
    <h3>ผลลัพธ์</h3>
    <div class="output" id="output"></div>
  </div>

  <script>
    const output = document.getElementById('output');
    
    function log(msg) {
      output.textContent += msg + '\n';
    }
    
    function clear() { output.textContent = ''; }
    
    function testBasic() {
      clear();
      const patterns = [
        /hello/,
        /hello world/,
        /\d+/,
        /\w+/,
        /[a-z]+/,
        /^.+$/
      ];
      
      patterns.forEach(re => {
        log(`Regex: ${re} → toString(): ${re.toString()}`);
      });
    }
    
    function testFlags() {
      clear();
      const basePattern = 'test';
      const flags = ['', 'g', 'i', 'm', 'gi', 'gim', 's', 'u', 'y'];
      
      flags.forEach(flag => {
        const re = new RegExp(basePattern, flag);
        log(`new RegExp('${basePattern}', '${flag}') → ${re.toString()}`);
      });
      
      log('\n--- Combined flags ---');
      log(`new RegExp('abc', 'gimu') → ${new RegExp('abc', 'gimu').toString()}`);
    }
    
    function testSpecialChars() {
      clear();
      // ตัวอักษรพิเศษที่ต้อง escape ใน regex
      const specials = ['*', '+', '?', '^', '$', '.', '|', '(', ')', '[', ']', '{', '}', '\\', '/'];
      
      specials.forEach(char => {
        const re = new RegExp(char);
        log(`Char: "${char}" → Regex: ${re.toString()}`);
      });
      
      log('\n--- Escaped in pattern ---');
      const re = /a\/b\?c\*d/;
      log(`Literal: /a\\/b\\?c\\*d/ → toString(): ${re.toString()}`);
    }
    
    function testConstructors() {
      clear();
      // Constructor pattern (string) vs Literal
      const strPattern = 'hello\\sworld';
      const re1 = new RegExp(strPattern);      // จาก string
      const re2 = /hello\sworld/;              // literal
      
      log(`String pattern: "${strPattern}"`);
      log(`new RegExp(pattern) → ${re1.toString()}`);
      log(`Literal /hello\\\\sworld/ → ${re2.toString()}`);
      log(`Are they equal? ${re1.toString() === re2.toString()}`);
      
      log('\n--- With flags ---');
      const re3 = new RegExp(strPattern, 'gi');
      const re4 = /hello\sworld/gi;
      log(`new RegExp(pattern, 'gi') → ${re3.toString()}`);
      log(`Literal /hello\\\\sworld/gi → ${re4.toString()}`);
    }
  </script>
</body>
</html>

ผลลัพธ์ตัวอย่าง

Regex: /hello/ → toString(): /hello/
Regex: /hello world/ → toString(): /hello world/
Regex: /\d+/ → toString(): /\d+/
Regex: /[a-z]+/ → toString(): /[a-z]+/
Regex: /^.+$/ → toString(): /^.+$/

new RegExp('test', 'g') → /test/g
new RegExp('test', 'i') → /test/i
new RegExp('test', 'gi') → /test/gi
new RegExp('test', 'gimu') → /test/gimu

Char: "*" → Regex: /\*/
Char: "?" → Regex: /\?/
Char: "/" → Regex: /\//  (slash ต้อง escape ใน literal)

Literal: /a\/b\?c\*d/ → toString(): /a\/b\?c\*d/

RegExp Flags ใคร่รู้จัก

Flagชื่อคำอธิบาย
gGlobalหาทุก match ใน string (ไม่หยุดที่ match แรก)
iIgnore Caseไม่สนใจตัวพิมพ์ใหญ่/เล็ก
mMultiline^ และ $ match ทุกบรรทัด
sDotAll. match newline ด้วย (ES2018)
uUnicodeรองรับ Unicode code points (ES2015)
yStickyMatch ต้องเริ่มที่ lastIndex เท่านั้น (ES2015)
dIndicesคืนค่า indices ของ match (ES2022)

การใช้งานจริง

1. Debugging / Logging

function logRegex(regex) {
  console.log(`Pattern: ${regex.toString()}`);
  console.log(`Source: ${regex.source}`);
  console.log(`Flags: ${regex.flags}`);
}

2. Dynamic Regex Construction

function buildSearchRegex(query, options = {}) {
  const flags = [
    options.global ? 'g' : '',
    options.ignoreCase ? 'i' : '',
    options.multiline ? 'm' : ''
  ].join('');
  
  // Escape special regex chars in user input
  const escaped = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  const regex = new RegExp(escaped, flags);
  
  console.log('Created regex:', regex.toString());
  return regex;
}

3. Serialize/Store Regex

// บันทึกลง localStorage / Database
const patterns = [
  { name: 'email', regex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ },
  { name: 'phone', regex: /^\+?[\d\s-]{10,}$/ }
];

const serialized = patterns.map(p => ({
  name: p.name,
  pattern: p.regex.source,
  flags: p.regex.flags
}));

// นำกลับมาใช้
const restored = serialized.map(p => new RegExp(p.pattern, p.flags));

ความแตกต่าง: toString() vs source vs flags

Property/Methodคืนค่าตัวอย่าง
regex.toString()Full literal string"/hello/gi"
regex.sourcePattern only (no slashes, no flags)"hello"
regex.flagsFlags only"gi"