संघनन के लिए + इतना बुरा क्यों है?


44

हर कोई यह कहता रहता है कि स्ट्रिंग समालोचना के लिए जावास्क्रिप्ट में से एक समस्या +[ उदाहरण ] का उपयोग कर रहा है । कुछ लोग कहते हैं कि समस्या का उपयोग नहीं किया जा रहा है +, यह प्रकार है जबरदस्ती [पिछले उदाहरण से टिप्पणियां देखें]। लेकिन दृढ़ता से टाइप की जाने वाली भाषाएं बिना किसी समस्या के समवर्ती और मोटे प्रकारों के लिए + का उपयोग करती हैं। उदाहरण के लिए, C # में:

int number = 1;
MyObject obj = new MyObject();

var result = "Hello" + number + obj;
// is equivalent to
string result = "hello" + number.ToString() + obj.ToString();

तो ऐसा क्यों है कि जावास्क्रिप्ट में स्ट्रिंग संघनन इतनी बड़ी समस्या है?


17
कारण है कि यह है bad। कौन है Everyone?
नील

3
मुझे लगता है कि समस्या एक गणितीय ऑपरेटर है +। और यह कि समता प्रक्रिया + उस मानक प्रक्रिया को भ्रमित करती है। क्योंकि "हैलो" + नंबर काम कर सकता है + "हैलो" नहीं हो सकता है।
सोयलेंटग्रे

3
@ नील, मैं सहमत हूं - मैं जानना चाहता हूं कि इन सभी सवालों में कौन-कौन रहस्यमयी 'हर' हैं।
ग्रैंडमास्टरबी

संघनन के लिए + का उपयोग करना ठीक है। डायनेमिक टाइपिंग का उपयोग करना ठीक है। एक ही भाषा में दोनों का उपयोग करना बुरा है ^ एच ^ एच ^ एच अस्पष्टता की ओर जाता है।
गेरी

6
@ नील - "हर कोई" डगलस क्रॉकफोर्ड होगा। उन्होंने अपनी पुस्तक 'जावास्क्रिप्ट: द गुड पार्ट्स' में इसे "भयानक" के रूप में सूचीबद्ध किया है।
kirk.burleson

जवाबों:


68

जावास्क्रिप्ट कोड के इस टुकड़े पर विचार करें:

var a = 10;
var b = 20;
console.log('result is ' + a + b);

यह लॉग होगा

परिणाम 1020 है

सबसे अधिक संभावना यह नहीं है कि क्या इरादा था, और बग को ट्रैक करने के लिए एक कठिन हो सकता है।


4
अंतर्निहित समस्या का बहुत अच्छा चित्रण: स्ट्रिंग समतलन को अच्छी तरह से परिभाषित नहीं किया जाता है जब प्रकार (स्ट्रिंग + इंट + उदाहरण में इंट) मिश्रित हो जाते हैं। बेहतर रूप से परिभाषित शब्दार्थ के साथ एक पूरी तरह से अलग ऑपरेटर (जैसे पर्ल का '।') होना बेहतर है।
ब्रूस एडगर जूल

9
या इस के हल के लिए अजगर की तरह, रैप करने के लिए आप के लिए मजबूर किया जाएगा जो aऔर bमें str(a)और str(b)कॉल; अन्यथा, आप ए ValueError: cannot concatenate 'str' and 'int'
एपेक्स

6
@FrustratedWithFormsDesigner: कोष्ठक जोड़ें। 'result is ' + (a + b)
जॉन प्यार्इ जूल

18
बात यह है कि, C # में आप एक ही काम कर सकते हैं, और आपको एक ही परिणाम मिलेगा - System.Console.WriteLine("result is " + 10 + 20);लेकिन C # में कोई भी इस बारे में कोई शिकायत नहीं करता है। यही मैं नहीं समझता - यह जावास्क्रिप्ट के बारे में क्या है जो इसे और अधिक भ्रमित करता है?
विन्यासकर्ता

7
@configurator: क्योंकि लोगों को C # सही बताया गया है और जावास्क्रिप्ट भयानक है। वे दोनों गलत हैं, लेकिन एक भाषा की प्रतिष्ठा छड़ी करने के लिए लगती है, धारणाएं बहुत कुछ के लिए गणना करती हैं, खासकर इंटर्नेट पर।
gbjbaanb

43

जब आप "खराब" कहते हैं, तो क्या आपका मतलब "गलत" है या आपका मतलब "धीमा" है? गणितीय ऑपरेटर्स का उपयोग कर स्ट्रिंग संयोजन करने के बारे में तर्क यकीनन एक "गलत" तर्क है, लेकिन यह भी एक तर्क यह है कि का उपयोग किया जा करने के लिए है +करने के लिए एक बहुत स्ट्रिंग संयोजन के बहुत धीमी गति से हो सकता है।

"Hello" + numberजब हम प्रदर्शन के बारे में बात करते हैं, तो हम बात नहीं कर रहे हैं , हम एक लूप में इसे बार-बार जोड़कर अपेक्षाकृत बड़ी स्ट्रिंग बनाने की बात कर रहे हैं।

var combined = "";
for (var i = 0; i < 1000000; i++) {
    combined = combined + "hello ";
}

जावास्क्रिप्ट में (और उस मामले के लिए #) तार अपरिवर्तनीय हैं। उन्हें कभी नहीं बदला जा सकता है, केवल अन्य तारों के साथ बदल दिया गया है। आप शायद जानते हैं कि चर combined + "hello "को सीधे संशोधित नहीं करता है combined- ऑपरेशन एक नया स्ट्रिंग बनाता है जो दो तारों को एक साथ जोड़ने का परिणाम है, लेकिन आपको उस नए स्ट्रिंग को combinedचर में असाइन करना होगा यदि आप इसे बदलना चाहते हैं।

तो यह पाश क्या कर रहा है एक लाख अलग स्ट्रिंग ऑब्जेक्ट्स बना रहा है, और उनमें से 999,999 को फेंक रहा है। यह देखते हुए कि कई तार जो लगातार आकार में बढ़ रहे हैं, तेज नहीं है, और अब इसके बाद सफाई करने के लिए कचरा संग्रहकर्ता के पास बहुत काम है।

C # में ठीक वैसी ही समस्या है, जो StringBuilder वर्ग द्वारा उस वातावरण में हल की जाती है । जावास्क्रिप्ट में, आप उन सभी स्ट्रिंग्स का एक सरणी बनाकर बेहतर प्रदर्शन प्राप्त कर सकते हैं, जिन्हें आप संक्षिप्त करना चाहते हैं, और फिर उन्हें एक बार में एक साथ जोड़कर, एक लाख बार लूप के बजाय:

var parts = [];
for (var i = 0; i < 1000000; i++) {
    parts.push("hello");
}
var combined = parts.join(" ");

3
यह एक उत्कृष्ट उत्तर है। न केवल इस सवाल का जवाब दिया बल्कि इसे शिक्षित किया।
चार्ल्स स्प्रेबेरी

3
हालांकि इसका मतलब यह नहीं है कि यह पूरी तरह से प्रश्न से असंबंधित है।
विन्यासकर्ता

4
माफ़ करना। लगता है कि कम से कम 7 लोगों ने आपके प्रश्न को गलत तरीके से समझा था जिस तरह से यह शब्द था।
जोएल म्यूलर

9
पुन: प्रदर्शन: शायद 2011 में ऐसा हुआ था, लेकिन अब array_join विधि (v8 में कम से कम) की तुलना में + ऑपरेटर विधि बहुत तेज है। इस jsperf को देखें: jsperf.com/string-concatenation101
UpTheCreek

2
किसी भी विचार में शामिल होने का तरीका एक चरण में कई भागों में से एक स्ट्रिंग को कैसे उत्पन्न करता है, इसके बजाय एक-एक करके संयोजन करता है, इस प्रकार उन सभी मध्यवर्ती तारों को भी उत्पन्न करता है?
एंजेलो। हानेस

14

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

3 * 5 => 15
"3" * "5" => 15
2 + " fish" => "2 fish"
"3" + "5" => "35"  // hmmm...

शायद अधिक सरल, स्वचालित प्रकार के रूपांतरण की उपस्थिति में "+" को अधिभारित करने से + ऑपरेटर की अपेक्षित संबद्धता टूट जाती है:

("x" + 1) + 3 != "x" + (1 + 3)

2
इसके अलावा इसके अलावा की संपत्तियों की संपत्ति 3 + 5 == 5 + 3"3" + "5" != "5" + "3"
संघनन

10

स्ट्रिंग समवर्ती के लिए लाया गया विशिष्ट मुद्दा कुछ मुद्दों के आसपास घूमता है:

  1. +प्रतीक अतिभारित किया जा रहा
  2. साधारण गलतियाँ
  3. प्रोग्रामर आलसी हो रहे हैं

# 1

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

यदि आप वेरिएबल है aऔर b, और आप तैयार c = a + b, वहाँ एक अस्पष्टता के प्रकार पर निर्भर करता है aऔर b। यह अस्पष्टता आपको समस्या को कम करने के लिए अतिरिक्त कदम उठाने के लिए मजबूर करती है:

स्ट्रिंग कॉनैट:

c = '' + a + b;

इसके अलावा:

c = parseFloat(a) + parseFloat(b);

यह मुझे मेरे दूसरे बिंदु पर लाता है

# 2

यह गलती से इसे साकार किए बिना एक चर को गलती से एक कास्ट करने के लिए बहुत आसान है। यह भूलना आसान है कि आपका इनपुट एक स्ट्रिंग के रूप में आ रहा है:

a = prompt('Pick a number');
b = prompt('Pick a second number');
alert( a + b );

अनैच्छिक परिणाम देगा क्योंकि प्रॉम्प्ट इनपुट के स्ट्रिंग मान को लौटाता है।

# 3

टाइप करने की जरूरत है parseFloatया Number()हर बार जो मैं करना चाहता हूं वह थकाऊ और कष्टप्रद है। मुझे लगता है कि मैं अपने गतिशील प्रकारों को गड़बड़ाने के लिए याद रखने के लिए पर्याप्त स्मार्ट हूं, लेकिन इसका मतलब यह नहीं है कि मैंने कभी भी अपने गतिशील प्रकारों को गड़बड़ नहीं किया है । इस मामले की सच्चाई यह है कि मैं टाइप करने के लिए बहुत आलसी हूं parseFloatया Number()हर बार मैं इसके अलावा, क्योंकि मैं बहुत कुछ करता हूं ।

उपाय?

सभी भाषाओं का उपयोग +स्ट्रिंग संघनन के लिए नहीं किया जाता है। PHP .स्ट्रिंग्स को जोड़ने के लिए उपयोग करती है, जो जब आप संख्याओं को जोड़ना चाहते हैं और जब आप स्ट्रिंग्स में शामिल होना चाहते हैं, के बीच अंतर करने में मदद करता है।

किसी भी प्रतीक का उपयोग तारों को समतल करने के लिए किया जा सकता है, लेकिन अधिकांश पहले से ही उपयोग किए जाते हैं, और दोहराव से बचने के लिए सबसे अच्छा है। अगर मेरे पास मेरा रास्ता होता, तो मैं शायद _स्ट्रिंग्स में शामिल होने के लिए, और _वेरिएबल नामों को अस्वीकार कर देता।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.