क्या जावास्क्रिप्ट अपरिवर्तनीय या परिवर्तनशील तार का उपयोग करता है? क्या मुझे "स्ट्रिंग बिल्डर" की आवश्यकता है?
क्या जावास्क्रिप्ट अपरिवर्तनीय या परिवर्तनशील तार का उपयोग करता है? क्या मुझे "स्ट्रिंग बिल्डर" की आवश्यकता है?
जवाबों:
वे अपरिवर्तनीय हैं। आप कुछ के साथ एक स्ट्रिंग के भीतर एक चरित्र को बदल नहीं सकते var myString = "abbdef"; myString[2] = 'c'। स्ट्रिंग हेरफेर करने के तरीके जैसे trim, sliceनए तार लौटाते हैं।
उसी तरह, यदि आपके पास एक ही स्ट्रिंग के दो संदर्भ हैं, तो एक को संशोधित करना दूसरे को प्रभावित नहीं करता है
let a = b = "hello";
a = a + " world";
// b is not affected
हालाँकि, मैंने हमेशा यह सुना है कि ऐश ने अपने उत्तर में क्या उल्लेख किया है (कि एरे.जॉइन का उपयोग करना संघनन के लिए तेज है) इसलिए मैं स्ट्रिंग्स को अलग करने और स्ट्रैंगबुइटल में सबसे तेज़ तरीके से अमूर्त करने के विभिन्न तरीकों का परीक्षण करना चाहता था। मैंने यह देखने के लिए कुछ परीक्षण लिखे कि क्या यह सच है (यह नहीं है!)।
मेरा मानना था कि यह सबसे तेज़ तरीका होगा, हालांकि मैं यह सोचता रहा कि मेथड कॉल जोड़ने से यह धीमा हो सकता है ...
function StringBuilder() {
this._array = [];
this._index = 0;
}
StringBuilder.prototype.append = function (str) {
this._array[this._index] = str;
this._index++;
}
StringBuilder.prototype.toString = function () {
return this._array.join('');
}
यहां प्रदर्शन गति परीक्षण हैं। इन तीनों ने "Hello diggity dog"एक खाली स्ट्रिंग में एक सौ हज़ार बार घनीभूत होकर एक विशालकाय तार का निर्माण किया ।
मैंने तीन प्रकार के परीक्षण बनाए हैं
Array.pushऔरArray.joinArray.pushउपयोग करनाArray.joinफिर मैंने उन्हें अमूर्त करके तीन ही टेस्ट बनाए StringBuilderConcat, StringBuilderArrayPushऔर StringBuilderArrayIndex http://jsperf.com/string-concat-without-sringbuilder/5 कृपया वहां जाएं और टेस्ट चलाएं ताकि हमें एक अच्छा नमूना मिल सके। ध्यान दें कि मैंने एक छोटा बग तय किया है, इसलिए परीक्षणों के लिए डेटा मिटा दिया गया है, एक बार पर्याप्त प्रदर्शन डेटा होने पर मैं तालिका को अपडेट कर दूंगा। पुराने डेटा टेबल के लिए http://jsperf.com/string-concat-without-sringbuilder/5 पर जाएं ।
यदि आप लिंक का अनुसरण नहीं करना चाहते हैं तो यहां कुछ नंबर (Ma5rch 2018 में नवीनतम अपडेट) दिए गए हैं। प्रत्येक परीक्षण पर संख्या 1000 संचालन / सेकंड ( उच्चतर बेहतर है )
| Browser | Index | Push | Concat | SBIndex | SBPush | SBConcat |
---------------------------------------------------------------------------
| Chrome 71.0.3578 | 988 | 1006 | 2902 | 963 | 1008 | 2902 |
| Firefox 65 | 1979 | 1902 | 2197 | 1917 | 1873 | 1953 |
| Edge | 593 | 373 | 952 | 361 | 415 | 444 |
| Exploder 11 | 655 | 532 | 761 | 537 | 567 | 387 |
| Opera 58.0.3135 | 1135 | 1200 | 4357 | 1137 | 1188 | 4294 |
जाँच - परिणाम
आजकल, सभी सदाबहार ब्राउज़रों ने स्ट्रिंग संयोजन को अच्छी तरह से संभाल लिया है। Array.joinकेवल IE 11 में मदद करता है
कुल मिलाकर, ओपेरा सबसे तेज है, अर्रे.जॉइन की तुलना में 4 गुना तेज है
फ़ायरफ़ॉक्स दूसरा है और Array.joinकेवल FF में थोड़ा धीमा है लेकिन क्रोम में काफी धीमा (3x) है।
Chrome तीसरा है लेकिन Array.join की तुलना में स्ट्रिंग कॉनैट 3 गुना तेज है
ऐसा लगता है कि StringBuilder बनाना पूर्णता को बहुत अधिक प्रभावित नहीं करता है।
आशा है कि किसी और को यह उपयोगी लगता है
अलग-अलग टेस्ट केस
चूंकि @RoyTinker ने सोचा था कि मेरा परीक्षण त्रुटिपूर्ण था, मैंने एक नया मामला बनाया जो एक ही स्ट्रिंग को समेट कर एक बड़ा स्ट्रिंग नहीं बनाता है, यह प्रत्येक पुनरावृत्ति के लिए एक अलग वर्ण का उपयोग करता है। स्ट्रिंग संघनन अभी भी तेज या सिर्फ तेज लग रहा था। चलिए वो टेस्ट चल रहे हैं।
मेरा सुझाव है कि हर किसी को इसे परखने के अन्य तरीकों के बारे में सोचना चाहिए, और नीचे दिए गए अलग-अलग परीक्षण मामलों में नए लिंक जोड़ने के लिए स्वतंत्र महसूस करना चाहिए।
joinबनाम स्ट्रिंग संघनन की एक सख्त तुलना में संकीर्ण करना था , इसलिए परीक्षण से पहले सरणी का निर्माण करना। मुझे नहीं लगता कि यह धोखा है अगर उस लक्ष्य को समझा जाता है (और joinसरणी को आंतरिक रूप से माना जाता है , इसलिए यह परीक्षण forसे लूप को धोखा देने के लिए धोखा नहीं है join, या तो)।
Array.join
से राइनो किताब :
जावास्क्रिप्ट में, स्ट्रिंग्स अपरिवर्तनीय वस्तुएं हैं, जिसका अर्थ है कि उनके भीतर के वर्णों को नहीं बदला जा सकता है और यह कि स्ट्रिंग्स पर कोई भी ऑपरेशन वास्तव में नए स्ट्रिंग्स बनाते हैं। स्ट्रिंग्स को संदर्भ द्वारा निर्दिष्ट किया जाता है, मूल्य द्वारा नहीं। सामान्य तौर पर, जब किसी ऑब्जेक्ट को संदर्भ द्वारा असाइन किया जाता है, तो ऑब्जेक्ट के लिए अन्य सभी संदर्भों के माध्यम से ऑब्जेक्ट में किए गए एक परिवर्तन दिखाई देगा। क्योंकि स्ट्रिंग को बदला नहीं जा सकता है, हालाँकि, आपके पास एक स्ट्रिंग ऑब्जेक्ट के कई संदर्भ हो सकते हैं और चिंता न करें कि स्ट्रिंग मूल्य आपके जानने के बिना बदल जाएगा
null undefined numberसे एक हैं boolean। स्ट्रिंग्स को मूल्य द्वारा निर्दिष्ट किया जाता है और संदर्भ द्वारा नहीं और इस तरह से पारित किया जाता है। इस प्रकार, तार सिर्फ अपरिवर्तनीय नहीं हैं, वे एक मूल्य हैं । स्ट्रिंग "hello"को बदलना यह "world"तय करने जैसा है कि अब से नंबर 3 पर नंबर 4 है ... इसका कोई मतलब नहीं है।
var a = "hello";var b=a;a.x=5;console.log(a.x,b.x);
Stringस्ट्रिंग कंस्ट्रक्टर का उपयोग करके बनाई गई ऑब्जेक्ट जावास्क्रिप्ट स्ट्रिंग मानों के आसपास रैपर हैं। आप .valueOf()फ़ंक्शन का उपयोग करके बॉक्सिंग प्रकार के स्ट्रिंग मूल्य तक पहुंच सकते हैं - यह Numberवस्तुओं और संख्या मूल्यों के लिए भी सही है। यह नोट करना महत्वपूर्ण है कि Stringउपयोग की गई वस्तुएं new Stringवास्तविक तार नहीं हैं बल्कि आवरण या हैं तार के आसपास बॉक्स हैं। Es5.github.io/#x15.5.2.1 देखें । वस्तुओं के रूप में चीजों को परिवर्तित करने के बारे में es5.github.io/#x9.9
प्रदर्शन टिप:
यदि आपको बड़े तारों को समतल करना है, तो स्ट्रिंग भागों को एक सरणी में रखें और Array.Join()समग्र स्ट्रिंग प्राप्त करने के लिए विधि का उपयोग करें । बड़ी संख्या में तारों को समतल करने के लिए यह कई गुना तेज हो सकता है।
StringBuilderजावास्क्रिप्ट में कोई भी नहीं है।
बस सरल मन के लिए स्पष्ट करने के लिए मेरा ( एमडीएन से ):
अपरिवर्तनीय वस्तुएं हैं जिनका ऑब्जेक्ट बनने के बाद स्थिति को बदला नहीं जा सकता है।
स्ट्रिंग और नंबर अपरिवर्तनीय हैं।
अपरिवर्तनीय का अर्थ है:
आप एक नया नाम पर एक चर नाम बिंदु बना सकते हैं, लेकिन पिछला मान अभी भी स्मृति में है। इसलिए कचरा संग्रहण की आवश्यकता है।
var immutableString = "Hello";// उपरोक्त कोड में, स्ट्रिंग मान के साथ एक नई वस्तु बनाई गई है।
immutableString = immutableString + "World";// अब हम मौजूदा मूल्य के लिए "विश्व" जोड़ रहे हैं।
ऐसा लगता है कि हम स्ट्रिंग को 'अपरिवर्तनीय स्ट्रिंग' के रूप में बदल रहे हैं, लेकिन हम नहीं हैं। बजाय:
एक स्ट्रिंग मान के साथ "इम्यूटेबल स्ट्रिंग" को जोड़ने पर, निम्नलिखित घटनाएं होती हैं:
- "ImmutableString" का मौजूदा मूल्य पुनर्प्राप्त किया जाता है
- "वर्ल्ड" को "इम्यूटेबल स्ट्रींग" के मौजूदा मूल्य से जोड़ा गया है
- परिणामी मान को फिर मेमोरी के एक नए ब्लॉक में आवंटित किया जाता है
- "immutableString" ऑब्जेक्ट अब नए बनाए गए मेमोरी स्पेस की ओर इशारा करता है
- पहले निर्मित मेमोरी स्पेस अब कचरा संग्रहण के लिए उपलब्ध है।
स्ट्रिंग प्रकार का मान अपरिवर्तनीय है, लेकिन स्ट्रिंग ऑब्जेक्ट, जो स्ट्रिंग () कंस्ट्रक्टर का उपयोग करके बनाया गया है, वह परिवर्तनशील है, क्योंकि यह एक ऑब्जेक्ट है और आप इसमें नए गुण जोड़ सकते हैं।
> var str = new String("test")
undefined
> str
[String: 'test']
> str.newProp = "some value"
'some value'
> str
{ [String: 'test'] newProp: 'some value' }
इस बीच, यद्यपि आप नए गुण जोड़ सकते हैं, आप पहले से मौजूद गुणों को नहीं बदल सकते
क्रोम कंसोल में एक परीक्षण का स्क्रीनशॉट
निष्कर्ष में, 1. सभी स्ट्रिंग प्रकार मान (आदिम प्रकार) अपरिवर्तनीय है। 2. स्ट्रिंग ऑब्जेक्ट उत्परिवर्तनीय है, लेकिन इसमें शामिल स्ट्रिंग प्रकार मान (आदिम प्रकार) अपरिवर्तनीय है।
new Stringएक अपरिवर्तनीय स्ट्रिंग के आसपास एक उत्परिवर्तनीय आवरण उत्पन्न करता है
Stringऑब्जेक्ट (आवरण) में पूरी तरह से नए गुण जोड़ सकते हैं , जिसका अर्थ है कि यह अपरिवर्तनीय नहीं है (डिफ़ॉल्ट रूप से, किसी अन्य ऑब्जेक्ट की तरह आप Object.freezeइसे अपरिवर्तनीय प्रदान करने के लिए कॉल कर सकते हैं )। लेकिन एक आदिम स्ट्रिंग मान प्रकार, चाहे वह Stringऑब्जेक्ट रैपर में निहित हो या नहीं, हमेशा अपरिवर्तनीय होता है।
ASP.NET Ajax में StringBuilder के बारे में आपके सवाल (ऐश की प्रतिक्रिया के बारे में आपकी टिप्पणी) के बारे में विशेषज्ञ इस पर असहमत लगते हैं।
क्रिश्चियन वेनज़ ने अपनी पुस्तक प्रोग्रामिंग एएसपी.एक्स.एक्सएक्स (ओ'रेली) में कहा है कि "इस दृष्टिकोण का मेमोरी पर कोई औसत दर्जे का प्रभाव नहीं होता है (वास्तव में, कार्यान्वयन मानक दृष्टिकोण की तुलना में एक टिक धीमा लगता है)।"
दूसरी ओर गैलो एट अल अपनी पुस्तक ASP.NET AJAX इन एक्शन (मैनिंग) में कहते हैं कि "जब समतल करने के लिए तारों की संख्या बड़ी होती है, तो स्ट्रिंग बिल्डर विशाल प्रदर्शन ड्रॉप से बचने के लिए एक आवश्यक वस्तु बन जाता है।"
मुझे लगता है कि आपको अपने स्वयं के बेंचमार्किंग करने की आवश्यकता होगी और परिणाम ब्राउज़रों के बीच भी भिन्न हो सकते हैं। हालाँकि, भले ही यह प्रदर्शन में सुधार नहीं करता है, फिर भी इसे प्रोग्रामर के लिए "उपयोगी" माना जा सकता है, जिन्हें C # या Java जैसी भाषाओं में StringBuilders के साथ कोडिंग करने के लिए उपयोग किया जाता है।
यह एक देर से पोस्ट है, लेकिन मुझे जवाबों के बीच एक अच्छी पुस्तक उद्धरण नहीं मिला।
यहाँ एक विश्वसनीय पुस्तक को छोड़कर एक निश्चित है:
ECMAScript में स्ट्रिंग्स अपरिवर्तनीय हैं, जिसका अर्थ है कि एक बार बनने के बाद, उनके मान बदल नहीं सकते हैं। एक चर द्वारा आयोजित स्ट्रिंग को बदलने के लिए, मूल स्ट्रिंग को नष्ट कर दिया जाना चाहिए और एक नया मूल्य युक्त एक अन्य स्ट्रिंग से भरा हुआ चर ... - वेब डेवलपर्स के लिए व्यावसायिक जावास्क्रिप्ट, तीसरा संस्करण।, p.43
अब, जो उत्तर राइनो पुस्तक के उद्धरण उद्धृत करता है, वह स्ट्रिंग अपरिवर्तनीयता के बारे में सही है, लेकिन गलत है "स्ट्रिंग्स को संदर्भ द्वारा निर्दिष्ट किया जाता है, मूल्य द्वारा नहीं।" (शायद वे मूल रूप से शब्दों को विपरीत तरीके से रखना चाहते थे)।
"प्रोफेशनल जावास्क्रिप्ट", "आदिम और संदर्भ मूल्य" नामक अध्याय में "संदर्भ / मूल्य" गलत धारणा को स्पष्ट किया गया है:
पाँच आदिम प्रकार ... [हैं]: अपरिभाषित, अशक्त, बूलियन, संख्या और स्ट्रिंग। इन चरों को मान से अभिगम करने के लिए कहा जाता है, क्योंकि आप चर में संग्रहीत वास्तविक मान में हेरफेर कर रहे हैं। वेब डेवलपर्स के लिए पेशेवर जावास्क्रिप्ट, तीसरा संस्करण।, p.85
यह वस्तुओं के विपरीत है :
जब आप किसी ऑब्जेक्ट में हेरफेर करते हैं, तो आप वास्तव में वास्तविक ऑब्जेक्ट के बजाय उस ऑब्जेक्ट के संदर्भ में काम कर रहे होते हैं। इस कारण से, इस तरह के मूल्यों को संदर्भ द्वारा एक्सेस करने के लिए कहा जाता है। वेब डेवलपर्स के लिए पेशेवर जावास्क्रिप्ट, तीसरा संस्करण।, p.85
जावास्क्रिप्ट स्ट्रिंग्स वास्तव में अपरिवर्तनीय हैं।
जावास्क्रिप्ट में तार अपरिवर्तनीय हैं