`String` वस्तु

यह लेख String वस्तु को समझाता है।

इस व्याख्या में मूल बातें से लेकर उन्नत तकनीकों तक सभी चीजें शामिल हैं, जिनमें यूनिकोड और रेगुलर एक्सप्रेशन से जुड़ी समस्याएँ भी क़दम दर क़दम और आसान भाषा में समझाई गई हैं।

YouTube Video

String वस्तु

JavaScript में स्ट्रिंग्स रोज़मर्रा के विकास में सबसे अधिक इस्तेमाल होने वाले प्रकारों में से एक हैं।

प्रिमिटिव स्ट्रिंग्स और स्ट्रिंग ऑब्जेक्ट्स के बीच अंतर

प्रिमिटिव स्ट्रिंग्स (जैसे "hello") का व्यवहार रैपर ऑब्जेक्ट्स जैसे new String("hello") से अलग होता है। आम तौर पर आपको प्रिमिटिव्स का ही उपयोग करना चाहिए, ऑब्जेक्ट रूप का इस्तेमाल करने की बहुत कम संभावना होती है।

1// Primitive string
2const a = "hello";
3
4// String wrapper object
5const b = new String("hello");
6
7console.log(typeof a); // "string"
8console.log(typeof b); // "object"
9console.log(a === b);  // false — wrapper objects are not strictly equal
  • यह कोड एक प्रिमिटिव और एक रैपर के बीच टाइप का अंतर और सख्त तुलना में उनके व्यवहार को दर्शाता है। अधिकतर मामलों में new String() का इस्तेमाल न करें और प्रिमिटिव्स का ही प्रयोग करें।

स्ट्रिंग्स बनाने के तरीके (लिटरल्स और टेम्पलेट लिटरल्स)

टेम्पलेट लिटरल्स वेरिएबल्स एम्बेड करने और मल्टी-लाइन स्ट्रिंग्स लिखने के लिए उपयोगी हैं। आप सहजता से वेरिएबल्स जोड़ सकते हैं और एक्सप्रेशंस का मूल्यांकन कर सकते हैं।

1const name = "Alice";
2const age = 30;
3
4// Template literal
5const greeting = `Name: ${name}, Age: ${age + 1}`;
6
7console.log(greeting); // "Name: Alice, Age: 31"
  • टेम्पलेट लिटरल्स अत्यंत पठनीय होते हैं और जटिल, मल्टी-लाइन स्ट्रिंग्स बनाने के लिए आदर्श हैं।

आम विधियाँ (खोजना और सबस्ट्रिंग निकालना)

String वस्तु में कई मूलभूत विधियाँ होती हैं।

 1const text = "Hello, world! Hello again.";
 2
 3// search
 4console.log(text.indexOf("Hello"));       // 0
 5console.log(text.indexOf("Hello", 1));    // 13
 6console.log(text.includes("world"));      // true
 7console.log(text.startsWith("Hello"));    // true
 8console.log(text.endsWith("again."));     // true
 9
10// slice / substring
11console.log(text.slice(7, 12));           // "world"
12console.log(text.substring(7, 12));       // "world"
  • slice और substring समान हैं, लेकिन वे नकारात्मक इंडेक्स को अलग तरीके से संभालते हैं। slice नकारात्मक मानों को अंतिम से स्थान के रूप में लेता है। कौन सा उपयोग करना है, इसका स्पष्ट निर्णय लें।

विभाजन और जोड़ (split / join)

स्ट्रिंग को प्रोसेसिंग के लिए एक ऐरे में विभाजित करना और बाद में फिर से जोड़ना सामान्य है।

1const csv = "red,green,blue";
2const arr = csv.split(","); // ["red","green","blue"]
3
4console.log(arr);
5console.log(arr.join(" | ")); // "red | green | blue"
  • एक आम तरीका है कि पहले split से स्ट्रिंग को विभाजित करें, map या filter से प्रोसेस करें, और फिर join से वापस जोड़ दें।

प्रतिस्थापन और रेगुलर एक्सप्रेशंस

replace केवल पहली मिलान को ही बदलता है। अगर आप सभी मिलान बदलना चाहते हैं, तो रेगुलर एक्सप्रेशन के साथ g फ्लैग का उपयोग करें। अगर आप प्रतिस्थापन के रूप में फ़ंक्शन पास करते हैं, तो आप डायनामिक रूप से भी प्रतिस्थापन कर सकते हैं।

 1const s = "foo 1 foo 2";
 2
 3// replace first only
 4console.log(s.replace("foo", "bar")); // "bar 1 foo 2"
 5
 6// replace all using regex
 7console.log(s.replace(/foo/g, "bar")); // "bar 1 bar 2"
 8
 9// replace with function
10const r = s.replace(/\d+/g, (match) => String(Number(match) * 10));
11console.log(r);    // "foo 10 foo 20"
  • फ़ंक्शन के साथ डायनामिक प्रतिस्थापन का उपयोग करके, आप संक्षिप्त रूप से ऐसा कोड लिख सकते हैं जो मैचों का विश्लेषण करें और उन्हें परिवर्तित करें।

अक्षर रूपांतरण और सामान्यीकरण

बहुभाषी समर्थन और तुलना के लिए, toLowerCase और toUpperCase के अलावा यूनिकोड सामान्यीकरण (normalize) भी महत्वपूर्ण है। यह विशेष रूप से उच्चारण चिह्न वाले अक्षरों की तुलना करते समय आवश्यक है।

 1// Case conversion example:
 2// "\u00DF" represents the German letter "ß".
 3// In some locales, converting "ß" to uppercase becomes "SS".
 4// JavaScript follows this behavior.
 5console.log("\u00DF");
 6console.log("\u00DF".toUpperCase()); // "SS"
 7
 8// Unicode normalization example:
 9// "e\u0301" is "e" + a combining acute accent.
10// "\u00e9" is the precomposed character "é".
11// These two look the same but are different code point sequences.
12const a = "e\u0301";
13const b = "\u00e9";
14
15console.log(a === b);   // false: different underlying code points
16console.log(a.normalize() === b.normalize()); // true: normalized to the same form
  • अलग-अलग यूनिकोड अभिव्यक्तियाँ, जैसे लिगेचर्स और संयोजन वर्ण, सीधे समान नहीं होंगी, इसलिए तुलना से पहले normalize() का उपयोग करें।

यूनिकोड और कोड पॉइंट्स (सरोगेट पेयर्स को संभालना)

JavaScript स्ट्रिंग्स UTF-16 कोड यूनिट्स का अनुक्रम होती हैं, इसलिए कुछ चिह्न जैसे इमोजी एक अक्षर के लिए दो कोड यूनिट्स ले सकते हैं। वास्तविक अक्षर यूनिट्स को संभालने के लिए, Array.from, स्प्रेड ऑपरेटर, या for...of का उपयोग करें।

 1// Emoji composed with multiple code points:
 2// "\u{1F469}" = woman, "\u{200D}" = Zero Width Joiner (ZWJ),
 3// "\u{1F4BB}" = laptop. Combined, they form a single emoji: 👩‍💻
 4const s = "\u{1F469}\u{200D}\u{1F4BB}";
 5console.log(s);
 6
 7// Length in UTF-16 code units (not actual Unicode characters):
 8// Because this emoji uses surrogate pairs + ZWJ, the length may be > 1.
 9console.log("Length:", s.length);
10
11// Iterate by Unicode code points (ES6 for...of iterates code points):
12// Each iteration gives a full Unicode character, not UTF-16 units.
13for (const ch of s) {
14  console.log(ch);
15}
16
17// Convert to an array of Unicode characters:
18console.log(Array.from(s));
  • length कोड यूनिट्स की संख्या लौटाता है, इसलिए इमोजी या लिगेचर्स के साथ अपेक्षित गणना नहीं मिल सकती। for...of और Array.from प्रकट होने वाले अक्षरों (ग्राफ़ीम क्लस्टर्स) के करीब काम करते हैं, लेकिन अगर आपको पूरी ग्राफ़ीम समर्थन चाहिए तो विशेष लाइब्रेरी का उपयोग करें।

सुरक्षित रेगुलर एक्सप्रेशन प्रतिस्थापन (यूज़र इनपुट के साथ)

यदि आप रेगुलर एक्सप्रेशन में उपयोगकर्ता इनपुट को एम्बेड करते समय उसे एस्केप करना भूल जाते हैं, तो यह अप्रत्याशित व्यवहार और कमजोरियों का कारण बन सकता है। पैटर्न में इस्तेमाल करने से पहले हमेशा यूज़र इनपुट को एस्केप करें।

1function escapeRegex(s) {
2  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3}
4
5const userInput = "a+b";
6const pattern = new RegExp(escapeRegex(userInput), "g");
7console.log("a+b a+b".replace(pattern, "X")); // "X X"
  • यूज़र स्ट्रिंग्स को रेगुलर एक्सप्रेशन में सीधे न डालें; हमेशा रेगेक्स बनाने से पहले उन्हें एस्केप करें।

प्रदर्शन सुझाव: संयोजन और टेम्पलेट्स

जब आपको कई छोटी स्ट्रिंग्स को लगातार जोड़ना हो, तो उन्हें ऐरे में डालकर join का उपयोग करना अधिक प्रभावी हो सकता है। वहीं, टेम्पलेट स्ट्रिंग्स भी ज़्यादातर मामलों में तेज़ और अत्यंत पठनीय होती हैं।

 1// concatenation in loop (less ideal)
 2let s = "";
 3for (let i = 0; i < 1000; i++) {
 4  s += i + ",";
 5}
 6
 7// using array + join (often faster for many pieces)
 8const parts = [];
 9for (let i = 0; i < 1000; i++) {
10  parts.push(i + ",");
11}
12const s2 = parts.join("");
  • आधुनिक JavaScript इंजन बहुत अनुकूलित हैं, इसलिए थोड़े बहुत संयोजन के लिए प्रदर्शन की चिंता नहीं करनी चाहिए। लेकिन, अगर आपको हज़ारों बार जोड़ना पड़े, तो join का उपयोग करना अधिक प्रभावी हो सकता है।

उपयोगी व्यावहारिक तकनीकें: पेडिंग, ट्रिम और रिपीट

trim, padStart, padEnd, और repeat ऐसे सुविधाजनक तरीके हैं जो रोज़मर्रा की स्ट्रिंग प्रोसेसिंग में विशेष रूप से उपयोगी हैं। इनका अक्सर व्यावहारिक परिस्थितियों में उपयोग किया जाता है, जैसे इनपुट मानों को फॉर्मेट करना या आउटपुट फ़ॉर्मेट्स को मानकीकृत करना।

1console.log("  hello  ".trim());       // "hello"
2console.log("5".padStart(3, "0"));     // "005"
3console.log("x".repeat(5));            // "xxxxx"
  • इन विधियों का उपयोग फॉर्म इनपुट सामान्यीकरण या फिक्स्ड-चौड़ाई आउटपुट बनाने में किया जा सकता है।

स्ट्रिंग तुलना (लोकेल तुलना)

localeCompare विभिन्न भाषाओं के शब्दकोश क्रम के अनुसार स्ट्रिंग्स की तुलना के लिए प्रभावी है। आप भाषा और संवेदनशीलता (जैसे केसी संवेदनशीलता) विकल्प निर्दिष्ट कर सकते हैं।

1console.log(
2  "\u00E4".localeCompare("z", "de")
3); // may be -1 or other depending on locale
4
5console.log(
6  "a".localeCompare("A", undefined, { sensitivity: "base" })
7); // 0
  • अंतरराष्ट्रीय तुलना के लिए, localeCompare का उपयोग करें और उचित लोकेल तथा विकल्प प्रदान करें।

व्यावहारिक उदाहरण: एक CSV पंक्ति को वस्तु में बदलना (व्यावहारिक कार्यप्रवाह)

एक सामान्य उपयोग यह है कि एक CSV पंक्ति को split, trim और map के संयोजन से ऑब्जेक्ट में पार्स किया जाए। उद्धृत फ़ील्ड्स या जटिल CSV फ़ाइलों के लिए, समर्पित CSV पार्सर का उपयोग करें।

 1// simple CSV parse (no quotes handling)
 2function parseCsvLine(line, headers) {
 3  const values = line.split(",").map(v => v.trim());
 4  const obj = {};
 5  headers.forEach((h, i) => obj[h] = values[i] ?? null);
 6  return obj;
 7}
 8
 9const headers = ["name", "age", "city"];
10const line = " Alice , 30 , New York ";
11console.log(parseCsvLine(line, headers));
12// { name: "Alice", age: "30", city: "New York" }
  • यह तरीका साधारण CSV में काम करता है, लेकिन अगर कॉमा उद्धृत फ़ील्ड में है तो यह काम नहीं करेगा।

सामान्य गलतियाँ

JavaScript स्ट्रिंग हैंडलिंग में कुछ ऐसी विशेषताएँ और व्यवहार हैं जिन्हें अक्सर अनदेखा कर दिया जाता है। अप्रत्याशित बग्स से बचने के लिए निम्न बिंदुओं का ध्यान रखना आवश्यक है।

  • new String() के उपयोग से टाइप जांच या तुलना में गलत परिणाम आ सकते हैं। ज्यादातर मामलों में प्रिमिटिव स्ट्रिंग प्रकार पर्याप्त हैं।
  • यूनिकोड में, एक ही दिखने वाला अक्षर कई कोड यूनिट्स से बना हो सकता है। इसलिए, length द्वारा लौटाई गई मात्रा वास्तव में प्रदर्शित अक्षरों की संख्या से मेल नहीं खा सकती।
  • यूज़र इनपुट को रेगुलर एक्सप्रेशन में डालने से पहले हमेशा उसे एस्केप करें।
  • String.prototype.replace() डिफ़ॉल्ट रूप से केवल पहली मिलान को बदलता है। यदि आप सभी स्थानों को बदलना चाहते हैं, तो अपने रेगुलर एक्सप्रेशन में '/g' फ्लैग का उपयोग करें।
  • स्ट्रिंग्स अपरिवर्तनीय होती हैं, इसलिए हर ऑपरेशन हमेशा एक नई स्ट्रिंग लौटाता है। लौटाई गई वैल्यू को हमेशा असाइन करना महत्वपूर्ण है।

सारांश

हालांकि JavaScript स्ट्रिंग्स सरल लगती हैं, लेकिन यूनिकोड और अपरिवर्तनीयता के उनके गुण जानना जरूरी है। मूल बातें अच्छे से जानकर आप अपनी स्ट्रिंग प्रोसेसिंग की विश्वसनीयता और पठनीयता काफी बढ़ा सकते हैं।

आप हमारे YouTube चैनल पर Visual Studio Code का उपयोग करके ऊपर दिए गए लेख के साथ आगे बढ़ सकते हैं। कृपया YouTube चैनल को भी देखें।

YouTube Video