JavaScript को कभी वैसा बनने के लिए नहीं बनाया गया था जैसा वह आज है। 1995 में, Brendan Eich ने Netscape में बैठकर दस दिनों में एक प्रोटोटाइप तैयार किया। दस दिन। यह एक अच्छी स्पेसिफिकेशन लिखने के लिए भी बहुत कम समय है, अरबों उपकरणों को शक्ति देने के लिए डिज़ाइन की गई एक प्रोग्रामिंग लैंग्वेज की बात तो दूर ही है। इसका परिणाम एक ऐसी भाषा के रूप में निकला जिसमें ऐसी खामियां (quirks) थीं जिनसे डेवलपर्स लगभग तीन दशक बाद भी टकराते रहते हैं। फिर भी, वही जल्दबाजी में किया गया निर्माण सॉफ्टवेयर इतिहास में सबसे व्यापक रूप से तैनात रनटाइम बन गया। यह इसलिए नहीं जीता क्योंकि यह सुरुचिपूर्ण (elegant) था, बल्कि इसलिए जीता क्योंकि यह ठीक उसी समय ब्राउज़र के भीतर उपलब्ध हुआ जब वेब को इसकी सबसे अधिक आवश्यकता थी।
जल्दबाजी में हुआ जन्म
नब्बे के दशक के मध्य के ब्राउज़र युद्ध कोई दोस्ताना मुकाबला नहीं थे। Netscape को एक हल्के-फुल्के (lightweight) स्क्रिप्टिंग लैंग्वेज की आवश्यकता थी जो उसके Navigator ब्राउज़र में Java के साथ चल सके। Eich को कुछ ऐसा बनाने का काम सौंपा गया था जो अधिकारियों को खुश करने के लिए काफी हद तक Java जैसा दिखे, लेकिन गैर-प्रोग्रामर्स के लिए वेब पेजों में पेस्ट करने के लिए पर्याप्त सरल हो। समय सीमा बेतुकी थी। उन्होंने Mocha बनाया, जिसका नाम जल्द ही बदलकर LiveScript कर दिया गया, और अंततः Java की लोकप्रियता का लाभ उठाने के लिए मार्केटिंग रणनीति के रूप में JavaScript नाम दिया गया।
उस जल्दबाजी में हुए जन्म ने स्थायी निशान छोड़ दिए। Type coercion अभी भी नए लोगों को भ्रमित करता है जब + ऑपरेटर बिना किसी चेतावनी के स्ट्रिंग्स और नंबरों को जोड़ (concatenate) देता है। typeof null मूल कार्यान्वयन (implementation) में एक बग के कारण "object" लौटाता है जिसे वेब को तोड़ने के डर से कोई ठीक करने की हिम्मत नहीं करता। Automatic semicolon insertion के कारण साइलेंट फेलियर (silent failures) होते हैं। var के साथ घोषित वेरिएबल ऐसे तरीकों से स्कोप लीक करते हैं जो अप्रत्याशित लगते हैं। ये कोई अमूर्त डिज़ाइन दोष नहीं हैं। ये दैनिक हताशाएं हैं जिनका सीधा संबंध मई 1995 के दो सप्ताह के स्प्रिंट से है।
एक अजीब वंशावली
JavaScript को ध्यान से देखें तो आपको तीन अलग-अलग वंश (lineages) जुड़े हुए दिखाई देंगे। इसका सिंटैक्स (syntax) काफी हद तक Java से लिया गया है। कर्ली ब्रेसेस (curly braces), if स्टेटमेंट्स और for लूप C-स्टाइल भाषाओं से आने वाले किसी भी व्यक्ति को एक परिचित आकार प्रदान करते हैं। लेकिन उस सतह के नीचे, व्यवहार पूरी तरह से अलग है।
भाषा का वास्तविक कम्प्यूटेशनल हृदय Scheme से आता है, जो Lisp का एक बोली (dialect) है। यहीं से JavaScript को first-class functions मिले, जिसका अर्थ है कि फंक्शन्स को आर्गुमेंट्स के रूप में पास किया जा सकता है, अन्य फंक्शन्स से वापस किया जा सकता है, और वेरिएबल्स को सौंपा जा सकता है। इसने हमें closures भी दिए, जो एक आंतरिक फंक्शन को बाहरी फंक्शन के निष्पादन (execution) के समाप्त होने के बाद भी उसके स्कोप तक पहुँचने की अनुमति देते हैं। यदि आपने कभी कोई callback लिखा है या event listener लगाया है, तो आपने Scheme से विरासत में मिले DNA का उपयोग किया है।
फिर इसका ऑब्जेक्ट मॉडल आता है, जो Self से लिया गया है। कठोर क्लासेस के साथ क्लासिकल इनहेरिटेंस के बजाय, JavaScript prototypes का उपयोग करता है। एक ऑब्जेक्ट सीधे दूसरे ऑब्जेक्ट से जुड़ सकता है और प्रॉपर्टी लुकअप को ऊपर की ओर डेलिगेट (delegate) कर सकता है। आप Object.create के साथ एक ऑब्जेक्ट बना सकते हैं और बिना किसी क्लास को परिभाषित किए चेन बना सकते हैं। आधुनिक JavaScript ने class कीवर्ड जोड़ा है, लेकिन यह मुख्य रूप से इस अंतर्निहित प्रोटोटाइप मशीनरी पर एक syntactic sugar है।
पेज की सजावट से एक गंभीर टूल तक
अपने पहले कुछ वर्षों के लिए, JavaScript छोटे काम करता था। यह सर्वर तक सबमिशन पहुँचने से पहले फॉर्म इनपुट को वैलिडेट करता था। यह माउस होवर पर इमेज बदलता था। यह एक खिलौना था, टूल नहीं। ब्राउज़र कार्यान्वयन असंगत थे, इसलिए डेवलपर्स अक्सर Netscape और Internet Explorer के लिए अलग-अलग कोड पाथ लिखते थे।
ECMAScript के माध्यम से मानकीकरण (Standardization) ने उस दिशा को बदल दिया। स्पेसिफिकेशन ने ब्राउज़र विक्रेताओं को लागू करने के लिए एक सामान्य लक्ष्य दिया, जिसने धीरे-धीरे सबसे खराब असंगतियों को दूर कर दिया। फिर Ajax आया।
Ajax, जिसका अर्थ Asynchronous JavaScript and XML है, कोई एक नई तकनीक नहीं थी बल्कि एक पैटर्न था जिसने मौजूदा हिस्सों को जोड़ा। महत्वपूर्ण घटक XMLHttpRequest ऑब्जेक्ट था, जिसने ब्राउज़र को पूरे पेज को रीलोड किए बिना बैकग्राउंड में सर्वर से डेटा मांगने की अनुमति दी। जब Google ने 2005 में Maps और 2004 में Gmail लॉन्च किया, तो उपयोगकर्ताओं ने अचानक ब्राउज़र टैब के भीतर डेस्कटॉप जैसी प्रतिक्रियाशीलता (responsiveness) का अनुभव किया। वेब पेज एप्लिकेशन बन गए। JavaScript अब केवल एक सजावट नहीं रह गया था। यह मुख्य व्यंजन (main course) बन गया था।
गति और महत्वाकांक्षा
कच्चा प्रदर्शन (Raw performance) कभी JavaScript का सबसे बड़ा मजाक हुआ करता था। शुरुआती इंटरप्रेटर धीमे थे। फिर Google ने 2008 में Chrome के साथ V8 इंजन जारी किया, और वह मजाक अब मजेदार नहीं रहा। V8 ने just-in-time compilation पेश किया, जो JavaScript को लाइन-दर-लाइन इंटरप्रेट करने के बजाय रनटाइम पर मशीन कोड में अनुवादित करता है। इसने डायनेमिक ऑब्जेक्ट्स पर भी प्रॉपर्टी एक्सेस को तेज़ बनाने के लिए hidden classes और inline caching पेश की। अन्य ब्राउज़रों ने अपने स्वयं के हाई-स्पीड इंजन के साथ प्रतिक्रिया दी, और भाषा अचानक वास्तविक गणना (computation) के लिए पर्याप्त तेज़ हो गई।
उस गति ने अगले बदलाव को संभव बनाया। Ryan Dahl ने 2009 में Node.js रिलीज़ किया, जिसमें V8 को ब्राउज़र से अलग करके उसे एक event-driven, non-blocking input-output मॉडल में लपेटा गया था। वेब सर्वर हर आने वाली रिक्वेस्ट के लिए एक नया thread बनाते थे, जो भारी concurrency के दबाव में ढह जाते थे। Node.js ने एक event loop और asynchronous callbacks का उपयोग करके एक ही thread पर हज़ारों एक साथ (simultaneous) कनेक्शनों को संभाला। JavaScript क्लाइंट से निकलकर सर्वर, बिल्ड टूल्स और अंततः हर चीज़ में फैल गया।
हर जगह मौजूद भाषा
अब JavaScript उन जगहों पर चलता है जिनकी कल्पना इसके निर्माता ने कभी नहीं की थी।
Frontend पर, React और Vue आधुनिक इंटरफेस के निर्माण के तरीके को आकार देते हैं। ब्राउज़र द्वारा महंगे full-page reloads किए बिना, state में बदलाव के जवाब में components अपडेट हो जाते हैं। Backend पर, Node.js APIs और real-time सेवाओं को शक्ति प्रदान करता है, जबकि Bun जैसे नए runtimes तेज़ package management और built-in bundling के साथ प्रयोग कर रहे हैं।
React Native JavaScript कोड को native platform views में अनुवादित करता है, जिससे टीमें Swift और Kotlin में दो पूरी तरह से अलग codebase बनाए बिना iOS और Android के लिए मोबाइल एप्लिकेशन लॉन्च कर सकती हैं। Electron डेस्कटॉप सॉफ़्टवेयर बनाने के लिए वेब तकनीकों को Chromium shell के भीतर लपेटता है, और इसी तरह Slack और Visual Studio Code दोनों आपके लैपटॉप तक पहुँचते हैं। यह भाषा cloud functions और edge computing workers के भीतर भी मौजूद है, जो distributed networks में एंड-यूज़र से कुछ ही मिलीसेकंड की दूरी पर लॉजिक को निष्पादित करती है।
प्रचुरता का विरोधाभास
सर्वव्यापकता की एक कीमत होती है। इसका ecosystem विशाल है, और यह आकार चिंता पैदा करता है। इससे पहले कि आप पिछले build tool को कॉन्फ़िगर करना समाप्त करें, एक नया build tool सामने आ जाता है। Frameworks की लोकप्रियता ऐसे समय अंतराल में घटती-बढ़ती है जो मौसमी महसूस होती है। आप JavaScript की दुनिया छोड़े बिना लगभग किसी भी समस्या का समाधान कर सकते हैं, लेकिन आपको पहले दर्जनों अत्यधिक विशिष्ट दृष्टिकोण वाले (opinionated) समाधानों में से किसी एक को चुनना होगा। Dependency trees गहरे और नाजुक होते जाते हैं। arrays को left-padding देने वाला एक package भी हज़ारों downstream projects को तोड़ सकता है जब वह registry से गायब हो जाता है।
इनमें से कुछ भी आकस्मिक नहीं है। JavaScript अव्यवस्थित है क्योंकि वेब अव्यवस्थित है। यह backward compatibility, जल्दबाजी में बनाए गए मानकों और प्रतिस्पर्धी कार्यान्वयन हितों का एक जैविक (organic) लेयर केक है। फिर भी वही अव्यवस्था इस भाषा को शक्तिशाली बनाती है। वेब हर जगह है, और क्योंकि JavaScript डिफ़ॉल्ट रूप से हर ब्राउज़र के भीतर रहता है, इसलिए यह एक universal runtime के सबसे करीब है।
यह बहुत पहले ही एक मात्र scripting language होना बंद कर चुका है। JavaScript अब सॉफ़्टवेयर के लिए एक वैश्विक मंच है, जिसे दस दिनों में बनाया गया था, और यह उस अदृश्य अनुबंध से जुड़ा हुआ है कि वेब को पिछली चीज़ों को नहीं तोड़ना चाहिए। इसकी ताकतों के साथ-साथ इसके निशानों को भी जानें, और आप आधुनिक इंटरनेट के इतिहास को ही सीख रहे होंगे।
