क्या जावास्क्रिप्ट का "नया" कीवर्ड हानिकारक माना जाता है? [बन्द है]


568

एक अन्य प्रश्न में , एक उपयोगकर्ता ने बताया कि newकीवर्ड का उपयोग करना खतरनाक था और ऑब्जेक्ट निर्माण का एक समाधान प्रस्तावित किया जो उपयोग नहीं किया new। मुझे विश्वास नहीं था कि यह सच था, क्योंकि मैंने प्रोटोटाइप, स्क्रिप्टैकुलस और अन्य उत्कृष्ट जावास्क्रिप्ट पुस्तकालयों का उपयोग किया है, और उनमें से सभी ने newकीवर्ड का उपयोग किया है ।

इसके बावजूद, कल मैं YUI थिएटर में डगलस क्रॉकफोर्ड की बात देख रहा था और उन्होंने ठीक यही बात कही, कि उन्होंने newअपने कोड में अब कीवर्ड का उपयोग नहीं किया ( क्रॉकफोर्ड ऑन जावास्क्रिप्ट - एक्ट III: फंक्शन अल्टीमेट - 50-23) मिनट )।

क्या newकीवर्ड का उपयोग करना 'बुरा' है ? इसका उपयोग करने के फायदे और नुकसान क्या हैं?


90
नए कीवर्ड का उपयोग करना 'बुरा' नहीं है। लेकिन अगर आप इसे भूल जाते हैं, तो आप एक नियमित फ़ंक्शन के रूप में ऑब्जेक्ट कंस्ट्रक्टर को कॉल करेंगे। यदि आपका निर्माता इसके निष्पादन संदर्भ की जांच नहीं करता है, तो यह ध्यान नहीं देगा कि 'यह' नए उदाहरण के बजाय अलग-अलग ऑब्जेक्ट (आमतौर पर वैश्विक ऑब्जेक्ट) को इंगित करता है। इसलिए आपका निर्माता वैश्विक ऑब्जेक्ट (विंडो) में गुण और तरीके जोड़ रहा होगा। यदि आप हमेशा जांचते हैं कि ऑब्जेक्ट फ़ंक्शन में 'यह' आपके ऑब्जेक्ट का एक उदाहरण है, तो आपको कभी भी यह समस्या नहीं होगी।
क्रिस्टियन बी

5
मुझे यह समझ में नहीं आता है। एक तरफ डग के इस्तेमाल को हतोत्साहित करता है new। लेकिन जब आप YUI लाइब्रेरी को देखेंगे। आपको newहर जगह उपयोग करना होगा । इस तरह के रूप में var myDataSource = new Y.DataSource.IO({source:"./myScript.php"});
आदित्य_गौर

2
@aditya_gaur ऐसा इसलिए है क्योंकि यदि आपको किसी ऑब्जेक्ट के आरंभीकरण की आवश्यकता है, initतो आपको एक तरीका हैक करना होगा यदि आप Object.createदृष्टिकोण का उपयोग कर रहे हैं और उसके बाद कॉल करेंगे। बहुत आसान है बस newजो दोनों का उपयोग करता है, प्रोटोटाइप चेन सेट करता है और कुछ इनिशलाइज़र कोड को कॉल करता है।
जुआन मेंडेस

67
मुझे नहीं लगता कि इसे बंद किया जाना चाहिए था। हां, यह कुछ क्रॉकफोर्ड विरोधी प्रशंसक विष को प्रेरित करने की संभावना है, लेकिन हम यहां एक प्रमुख भाषा सुविधा से बचने के लिए लोकप्रिय सलाह के बारे में बात कर रहे हैं। हर JQuery ऑब्जेक्ट को बनाने वाला तंत्र लगभग कुछ भी नहीं (जहाँ मेमोरी का संबंध है) 'नए' कीवर्ड का उपयोग करता है। कारखाने के तरीकों को लगातार नए बनाने के लिए प्राथमिकता दें, लेकिन केवल वस्तु शाब्दिक रूप से अपने वास्तु विकल्पों और प्रदर्शन क्षमता को बहुत कम न करें। उनके पास अपनी जगह है और निर्माणकर्ताओं के पास अपनी जगह है। यह हाथ से नीचे दिनांकित और घटिया सलाह है।
एरिक रेपेन

2
TLDR: का उपयोग करना newखतरनाक नहीं है। ओमिटिंग newखतरनाक है, और इसलिए खराब है । लेकिन ES5 में आप स्ट्रिक्ट मोड का उपयोग कर सकते हैं , जो आपको उस खतरे और कई अन्य लोगों से बचाता है।
जकदेव

जवाबों:


603

अच्छी जावास्क्रिप्ट तकनीकों को लोकप्रिय बनाने के लिए क्रॉकफोर्ड ने बहुत कुछ किया है। भाषा के प्रमुख तत्वों के बारे में उनकी राय ने कई उपयोगी चर्चाओं को जन्म दिया है। उस ने कहा, बहुत से लोग हैं जो "बुरे" या "हानिकारक" के प्रत्येक उद्घोष को सुसमाचार के रूप में लेते हैं, एक व्यक्ति की राय से परे देखने से इनकार करते हैं। यह कई बार थोड़ा निराश कर सकता है।

newकीवर्ड द्वारा प्रदान की गई कार्यक्षमता का उपयोग खरोंच से प्रत्येक वस्तु के निर्माण पर कई फायदे हैं:

  1. प्रोटोटाइप वंशानुक्रम । जबकि अक्सर क्लास-आधारित ओओ भाषाओं के आदी लोगों द्वारा संदेह और उपहास के मिश्रण के साथ देखा जाता है, जावास्क्रिप्ट की मूल विरासत तकनीक कोड री-यूज़ का एक सरल और आश्चर्यजनक प्रभावी साधन है। और नया कीवर्ड कैनोनिकल (और केवल उपलब्ध क्रॉस-प्लेटफॉर्म) इसका उपयोग करने का साधन है।
  2. प्रदर्शन। यह # 1 का एक साइड-इफ़ेक्ट है: यदि मैं अपने द्वारा बनाए गए प्रत्येक ऑब्जेक्ट में 10 विधियाँ जोड़ना चाहता हूँ, तो मैं केवल एक निर्माण फंक्शन लिख सकता हूँ जो प्रत्येक नए ऑब्जेक्ट को मैन्युअल रूप से असाइन करता है ... या, मैं उन्हें असाइन कर सकता हूँ निर्माण कार्य prototypeऔर newनई वस्तुओं पर मुहर लगाने के लिए उपयोग करें। न केवल यह तेज़ है (प्रोटोटाइप पर प्रत्येक और हर विधि के लिए आवश्यक कोई कोड नहीं है), यह प्रत्येक विधि के लिए अलग-अलग गुणों के साथ प्रत्येक वस्तु को गुब्बारा करने से बचता है। धीमी मशीन (या विशेष रूप से, धीमी जेएस दुभाषियों) पर जब कई ऑब्जेक्ट बनाए जा रहे हैं तो इसका मतलब समय और स्मृति में महत्वपूर्ण बचत हो सकती है।

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

function foo()
{
   // if user accidentally omits the new keyword, this will 
   // silently correct the problem...
   if ( !(this instanceof foo) )
      return new foo();

   // constructor logic follows...
}

अब आप newबिना गलती के दुरुपयोग के कारण होने वाली समस्याओं के बारे में चिंता किए बिना फायदे पा सकते हैं । अगर आप टूटे हुए कोड के बारे में चुपचाप काम कर रहे हैं, तो आपको इस बात पर ध्यान देने की ज़रूरत है कि आप जाँच कर सकते हैं। या, जैसा कि कुछ ने टिप्पणी की, रनटाइम अपवाद पेश करने के लिए चेक का उपयोग करें:

if ( !(this instanceof arguments.callee) ) 
   throw new Error("Constructor called as a function");

(ध्यान दें कि यह स्निपेट कंस्ट्रक्टर फ़ंक्शन नाम की हार्ड-कोडिंग से बचने में सक्षम है, क्योंकि पिछले उदाहरण के विपरीत इसे वास्तव में ऑब्जेक्ट को तुरंत करने की कोई आवश्यकता नहीं है - इसलिए, इसे संशोधन के बिना प्रत्येक लक्ष्य फ़ंक्शन में कॉपी किया जा सकता है।)

जॉन रेसिग अपनी सरल "क्लास" इंस्टेंटेशन पोस्ट में इस तकनीक पर विस्तार से जाते हैं , साथ ही डिफ़ॉल्ट रूप से इस व्यवहार को आपके "वर्गों" में बनाने का एक साधन भी शामिल है। निश्चित रूप से लायक एक पढ़ें ... के रूप में अपनी आने वाली किताब है, जावास्क्रिप्ट निंजा का राज है, जो यह और कई अन्य "हानिकारक" में सोने छिपा मिलते जावास्क्रिप्ट भाषा की विशेषताएं ( अध्याय पर withविशेष रूप से हम में से उन लोगों के लिए ज्ञानवर्धक है जो शुरू में खारिज कर दिया एक नौटंकी के रूप में यह बहुत बदनाम विशेषता)।


96
अगर ((यह इंस्ट्रूमेंट दलीलें। callee)) एरर ("कंस्ट्रक्टर को एक फंक्शन के रूप में कहा जाता है") को फेंक दें; // अधिक सामान्य, कंस्ट्रक्टर्स के नाम के ज्ञान की आवश्यकता नहीं है, उपयोगकर्ता को कोड ठीक करें।
कुछ

5
यदि आप प्रदर्शन के बारे में चिंतित हैं - और वास्तव में होने का कारण है - तो चेक बिल्कुल न करें। या तो आप के लिए याद करने के लिए newएक आवरण समारोह का उपयोग करें , या उपयोग करने के लिए याद रखें। मुझे संदेह है कि अगर आप उस बिंदु पर हैं जहां यह मायने रखता है, तो आप पहले से ही अन्य अनुकूलन जैसे कि
संस्मरण को

65
का उपयोग arguments.calleeकरता है, तो आप के साथ बुलाया गया है की जाँच करने के newबाद से इतना अच्छा नहीं हो सकता है, arguments.calleeकठोर मोड में उपलब्ध नहीं है। फ़ंक्शन नाम का उपयोग करने के लिए बेहतर है।
शॉन मैकमिलन

69
अगर मैं एक पहचानकर्ता को मिस करता हूं, तो मेरा कोड टूट जाता है। क्या मुझे पहचानकर्ताओं का उपयोग नहीं करना चाहिए? उपयोग नहीं कर रहा है newक्योंकि आप इसे अपने कोड में लिखना भूल सकते हैं मेरे उदाहरण के रूप में केवल हास्यास्पद है।
थॉमस एडिंग

16
यदि आप सख्त मोड को चालू करते हैं, यदि आप नए का उपयोग करना भूल जाते हैं तो आपको इसका उपयोग करने का प्रयास करने पर एक अपवाद मिलेगा: yuiblog.com/blog/2010/12/14/strict-mode-is-coming-to-town वह है प्रत्येक कंस्ट्रक्टर को चेक का एक उदाहरण जोड़ने से ज्यादा आसान है।
Stephenbez

182

मैंने अभी उनकी क्रॉकफ़ोर्ड पुस्तक "जावास्क्रिप्ट: द गुड पार्ट्स" के कुछ हिस्सों को पढ़ा है। मुझे यह महसूस होता है कि वह हर उस चीज पर विचार करता है, जिसने कभी उसे हानिकारक माना है:

स्विच फ़ॉल के बारे में:

मैं अगले मामलों में स्विच के मामलों को कभी भी गिरने नहीं देता। मुझे एक बार मेरे कोड में एक बग दिखाई दिया, जिसके बारे में एक जोरदार भाषण के बाद तुरंत एक जोरदार भाषण हुआ कि क्यों कभी-कभी गिरता है, उपयोगी था। (पृष्ठ 97, आईएसबीएन 978-0-596-51774-8)

++ और - के बारे में

++ (इंक्रीमेंट) और - (डिक्रीमेंट) ऑपरेटर्स को एक्सिसिव ट्रिकनेस को बढ़ावा देकर खराब कोड में योगदान करने के लिए जाना जाता है। वे वायरस और अन्य सुरक्षा खतरों को सक्षम करने में दोषपूर्ण वास्तुकला के बाद दूसरे स्थान पर हैं। (पृष्ठ 122)

नए के बारे में:

यदि आप कंस्ट्रक्टर फ़ंक्शन को कॉल करते समय नए उपसर्ग को शामिल करना भूल जाते हैं , तो यह नई ऑब्जेक्ट के लिए बाध्य नहीं होगा। अफसोस की बात यह है कि यह वैश्विक वस्तु के लिए बाध्य होगा, इसलिए अपनी नई वस्तु को बढ़ाने के बजाय, आप अन्य छोटे चर को रोकेंगे। यह वास्तव में बुरा है। कोई संकलन चेतावनी नहीं है, और कोई रनटाइम चेतावनी नहीं है। (पेज 49)

और भी हैं, लेकिन मुझे उम्मीद है कि आपको तस्वीर मिल जाएगी।

आपके प्रश्न का मेरा उत्तर: नहीं, यह हानिकारक नहीं है। लेकिन अगर आप इसका इस्तेमाल करना भूल जाते हैं जब आपको कुछ समस्याएं हो सकती हैं। यदि आप एक अच्छे वातावरण में विकसित कर रहे हैं तो आप उस पर ध्यान देते हैं।

अपडेट करें

इस उत्तर को लिखे जाने के लगभग एक साल बाद ECMAScript का 5 वां संस्करण जारी किया गया, जिसमें सख्त मोड का समर्थन था । सख्त मोड में, thisअब वैश्विक वस्तु के लिए बाध्य नहीं है , लेकिन करने के लिए undefined


3
मैं पूरी तरह से सहमत। समाधान: हमेशा यह दस्तावेज कि उपयोगकर्ताओं को आपकी वस्तुओं को त्वरित कैसे करना है। एक उदाहरण का उपयोग करें और उपयोगकर्ताओं को कटौती / पेस्ट की संभावना होगी। हर भाषा में ऐसे निर्माण / विशेषताएं हैं जिनका दुरुपयोग असामान्य / अप्रत्याशित व्यवहार के परिणामस्वरूप किया जा सकता है। यह उन्हें हानिकारक नहीं बनाता है।
nicerobot 15

45
एक ऊपरी केस लेटर के साथ हमेशा कंस्ट्रक्टर शुरू करने के लिए एक कन्वेंशन है, और कम केस लेटर के साथ अन्य सभी फंक्शन।
कुछ

61
मुझे बस एहसास हुआ कि क्रॉकफोर्ड हानिकारक नहीं मानते ... मुझे नहीं पता कि मैंने कितने समय के लिए एक इनफ़िनिटिव लूप बनाया है क्योंकि मैं एक चर में वृद्धि करना भूल गया हूं ...
कुछ

5
उसी के लिए जाता है ++, -। वे बिल्कुल वही व्यक्त करते हैं जो मैं स्पष्ट भाषा में करना चाहता हूं। मैं प्यार करता हूँ! स्विच फॉल थ्रू कुछ स्पष्ट हो सकता है, लेकिन मैं उन लोगों के बारे में परेशान हूं। मैं उनका उपयोग तब करता हूं जब वे स्पष्ट रूप से अधिक स्पष्ट होते हैं ('दंड का उपयोग करें, विरोध नहीं कर सकते)।
PEZ

30
क्रॉकफोर्ड के लिए मेरा जवाब: प्रोग्रामिंग कठिन है, खरीदारी करने देता है। शीश!
जेसन जैक्सन

91

जावास्क्रिप्ट को गतिशील भाषा होने के कारण एक गड़बड़ तरीका है जहाँ दूसरी भाषा आपको रोक देगी।

इस तरह newके आधार पर एक मूलभूत भाषा सुविधा से बचना , जो आपको गड़बड़ कर सकता है, यह है कि आप अपने जूते मैला हो सकता है के मामले में एक खान क्षेत्र से गुजरने से पहले अपने चमकदार नए जूते को हटाने की तरह है।

मैं एक कन्वेंशन का उपयोग करता हूं जहां फ़ंक्शन नाम एक कम केस लेटर और 'फ़ंक्शंस' से शुरू होते हैं जो वास्तव में क्लास परिभाषा होते हैं जो ऊपरी केस लेटर से शुरू होते हैं। परिणाम वास्तव में काफी सम्मोहक दृश्य सुराग है कि 'वाक्यविन्यास' गलत है: -

var o = MyClass();  // this is clearly wrong.

इस अच्छी नामकरण आदतों के शीर्ष पर मदद मिलती है। सभी कार्यों के बाद चीजें होती हैं और इसलिए इसके नाम में एक क्रिया होनी चाहिए जबकि कक्षाएं वस्तुओं का प्रतिनिधित्व करती हैं और संज्ञा और विशेषण हैं जिनमें कोई क्रिया नहीं है।

var o = chair() // Executing chair is daft.
var o = createChair() // makes sense.

यह दिलचस्प है कि एसओ के सिंटैक्स रंग ने ऊपर दिए गए कोड की व्याख्या कैसे की है।


8
हाँ, मैं सिंटेक्स रंग के बारे में एक ही बात सोच रहा था।
बॉबीशाफ्टो

4
एक बार मैं 'फंक्शन' शब्द लिखना भूल गया। शब्द को हर कीमत पर टाला जाना चाहिए। एक और बार मैं एक बहु लाइन में घुंघराले ब्रेसिज़ का उपयोग नहीं किया अगर / फिर बयान। तो अब मैं घुंघराले ब्रेसिज़ का उपयोग नहीं करता हूं और सिर्फ एक-पंक्ति सशर्त लिखता हूं।
हेल ​​50000

"यह स्पष्ट रूप से गलत है" । क्यों? मेरी कक्षाओं के लिए (जो बस करते हैं if (! this instanceof MyClass) return new MyClass()) मैं वास्तव में new-लेस सिंटैक्स पसंद करता हूं । क्यों? क्योंकि फ़ंक्शंस निर्माता कार्यों की तुलना में अधिक सामान्य हैं । बाहर जाने newसे एक कंस्ट्रक्टर फ़ंक्शन को एक नियमित फ़ंक्शन में बदलना आसान हो जाता है ... या दूसरे तरीके से। newकोड को जोड़ने की आवश्यकता से अधिक विशिष्ट बनाता है। और इसलिए कम लचीला। जावा के साथ तुलना करें जहां यह स्वीकार करने के लिए अनुशंसा की जाती है Listके बजाय ArrayListतो फोन करने वाले कार्यान्वयन चुन सकते हैं।
स्टिजन डे विट

41

मैं जावास्क्रिप्ट के लिए नौसिखिया हूं इसलिए शायद मैं इस बारे में एक अच्छा दृष्टिकोण प्रदान करने में बहुत अनुभवी नहीं हूं। फिर भी मैं इस "नई" चीज पर अपना विचार साझा करना चाहता हूं।

मैं सी # दुनिया से आया हूं जहां "नया" कीवर्ड का उपयोग करना इतना स्वाभाविक है कि यह फैक्टरी डिजाइन पैटर्न है जो मुझे अजीब लगता है।

जब मैं जावास्क्रिप्ट में पहली बार कोड करता हूं, तो मुझे यह महसूस नहीं होता है कि YUI पैटर्न में एक जैसा "नया" कीवर्ड और कोड है और मुझे आपदा में चलने में लंबा समय नहीं लगता है। मैं ट्रैक करता हूं कि एक विशेष पंक्ति को माना जाता है कि मैंने जो कोड लिखा है उसे वापस देख रहा हूं। अधिक अराजक यह है कि मेरा दिमाग वास्तव में ऑब्जेक्ट इंस्टेंसेस की सीमाओं के बीच पार नहीं कर सकता है जब मैं कोड "ड्राई-रनिंग" कर रहा हूं।

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

उदाहरण के लिए, var bar=foo();मेरे पास कोई सुराग नहीं है कि क्या बार संभवतः हो सकता है .... क्या यह एक वापसी मूल्य है या यह एक नव निर्मित वस्तु है? लेकिन var bar = new foo();मुझे यकीन है कि बार के लिए एक वस्तु है।


3
सहमत हुए, और मेरा मानना है कि कारखाना पैटर्न makeFoo () की तरह एक नामकरण का पालन करना चाहिए
pluckyglen

3
+1 - 'नई' की उपस्थिति मंशा का स्पष्ट विवरण देती है।
बेलुगबोब

4
यह प्रतिक्रिया अजीब तरह की है, जब जेएस में लगभग सब कुछ एक वस्तु है। आपको यह सुनिश्चित करने की आवश्यकता क्यों है कि एक फ़ंक्शन एक ऑब्जेक्ट है जब सभी फ़ंक्शन ऑब्जेक्ट होते हैं?
जोशुआ रामिरेज़

@JoshuaRamirez बिंदु यह नहीं है typeof new foo() == "object"। ऐसा लगता है कि newएक उदाहरण देता है foo, और आप जानते हैं कि आप कॉल कर सकते हैं foo.bar()और foo.bang()। हालाँकि, यह आसानी से JsDoc के @return का उपयोग करके कम किया जा सकता है न कि मैं प्रक्रियात्मक कोड (शब्द से बचने के लिए new) की वकालत कर रहा हूँ
जुआन मेंडेस

1
@JuanMendes हम्म ... आपकी पोस्ट से मुझे यह प्रतीत हुआ कि आपको अपने कोड बेस में स्पष्ट कीवर्ड के कारण नया पसंद आया है। मैं उसे खोद सकता हूं। इसलिए मैं एक मॉड्यूल पैटर्न का उपयोग करता हूं। मेरे पास एक फ़ंक्शन होगा जिसे createFoo या NewFoo या MakeFoo कहा जाता है, जब तक यह स्पष्ट नहीं होता तब तक कोई फर्क नहीं पड़ता। इसके अंदर मैं उन चरों को घोषित करता हूं जो किसी वस्तु शाब्दिक के अंदर क्लोजर के रूप में उपयोग किए जाते हैं जो फ़ंक्शन से वापस आ जाते हैं। वह वस्तु शाब्दिक आपकी वस्तु होने के नाते समाप्त हो जाती है, और फ़ंक्शन केवल एक निर्माण कार्य था।
यहोशू रामिरेज़

39

नए के लिए एक और मामला है जिसे मैं पूह कोडिंग कहता हूं । विनी द पूह ने अपनी ठुमरी लगाई। मैं जाकर कहते हैं कि के साथ आप जिस भाषा का प्रयोग कर रहे हैं नहीं के खिलाफ यह।

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

भाषा के इरादों के बाद लिखा गया कोड प्रत्येक रिलीज के साथ दक्षता में वृद्धि करेगा। और भाषा के प्रमुख निर्माण से बचने वाला कोड समय के साथ भुगतना होगा।

संपादित करें: और यह प्रदर्शन से परे है। मैं कई बार मैंने सुना है भरोसा कर सकते हैं (या कहा) "क्यों नरक वे करते हैं किया था कि ?" जब अजीब लग कोड मिल रहा है। यह अक्सर पता चलता है कि उस समय जब कोड लिखा गया था, उसके लिए कुछ "अच्छा" कारण था। भाषा के ताओ के बाद आपका सबसे अच्छा बीमा है, जिसके लिए आपके कोड का अब से कुछ वर्षों तक उपहास नहीं हुआ है।


3
पूह कोडिंग लिंक के लिए +1 - अब मुझे अपनी बातचीत में इसे काम करने के बहाने खोजने की जरूरत है ...
शोग

जबरदस्त हंसी! मुझे उस विशेष क्षेत्र में वर्षों का अनुभव है और मैं आपको आश्वस्त कर सकता हूं कि आपको कोई कठिनाई नहीं मिलेगी। वे अक्सर मुझे पूह को रॉबिकी.नेट पर बुलाते हैं। =)
PEZ

1
पता नहीं आप कभी इस टिप्पणी को देखेंगे, लेकिन यह पोह कोडिंग लिंक मृत है।
केल्विन

सर उठाने के लिए धन्यवाद। हमने पिछले हफ्ते robowiki.net को एक नई विकि पर माइग्रेट किया था और पुरानी सामग्री इस समय उपलब्ध नहीं है। मैं उन पुराने लिंक को काम करने के साथ जल्दी करूँगा।
PEZ

24

मैंने एक पोस्ट लिखा कि नए कीवर्ड के बिना कंस्ट्रक्टर को कॉल करने की समस्या को कैसे कम किया जाए।
यह अधिकांशतः शिक्षाप्रद है, लेकिन यह दर्शाता है कि आप किस तरह से या उसके बिना काम करने वाले निर्माणकर्ता बना सकते हैं newऔर आपको हर निर्माणकर्ता में परीक्षण के लिए बॉयलरप्लेट कोड जोड़ने की आवश्यकता नहीं है this

http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html

यहाँ तकनीक का सार है:

/**
 * Wraps the passed in constructor so it works with
 * or without the new keyword
 * @param {Function} realCtor The constructor function.
 *    Note that this is going to be wrapped
 *    and should not be used directly 
 */
function ctor(realCtor){
  // This is going to be the actual constructor
  return function wrapperCtor(){
    var obj; // object that will be created
    if (this instanceof wrapperCtor) {
      // Called with new
      obj = this;
    } else {
      // Called without new. Create an empty object of the
      // correct type without running that constructor
      surrogateCtor.prototype = wrapperCtor.prototype;
      obj = new surrogateCtor();
    }
    // Call the real constructor function
    realCtor.apply(obj, arguments);
    return obj;
  }

  function surrogateCtor() {}
}

इसका उपयोग कैसे करें:

// Create our point constructor
Point = ctor(function(x,y){
  this.x = x;
  this.y = y;
});

// This is good
var pt = new Point(20,30);
// This is OK also
var pt2 = Point(20,30);

6
टालना arguments.calleeकमाल का है!
ग्रेग लिंड

2
surrogateConstructorहोना चाहिए surrogateCtor(या इसके विपरीत)।
डेविड कॉनराड

मैंने इसी तरह के क्रॉकफोर्ड-प्रेरित उपयोगिताओं का एक संग्रह बनाए रखा, और पाया कि जब मैं एक नई परियोजना शुरू करता हूं, तो मुझे हमेशा कार्यान्वयन को खोजने के लिए दौड़ना पड़ता था। और यह प्रोग्रामिंग के इस तरह के एक मूलभूत हिस्से को लपेटता है: ऑब्जेक्ट इंस्टेंटेशन। यह सब काम, बस जल्दबाजी कोड को सक्षम करने के लिए? मैं ईमानदारी से इस आवरण की सरलता की सराहना करता हूं, लेकिन यह सिर्फ लापरवाह कोडिंग को बढ़ाता है।
जो कोडर

1
@joecoder मैंने इसका उल्लेख केवल उपदेशात्मक उद्देश्यों के लिए किया था, मैं कोडिंग की इस व्यामोह शैली की सदस्यता नहीं लेता। हालाँकि, अगर मैं एक क्लास लाइब्रेरी लिख रहा था, तो हाँ मैं इस फीचर को कॉलर्स के लिए पारदर्शी तरीके से जोड़ूंगा
जुआन मेंडेस

22

नए कीवर्ड का उपयोग न करने के पीछे तर्क सरल है:

इसका बिल्कुल भी उपयोग नहीं करने से, आप गलती से इसे छोड़ने के साथ आने वाले नुकसान से बच जाते हैं। YUI का उपयोग करने वाला निर्माण पैटर्न, इस बात का एक उदाहरण है कि आप नए कीवर्ड से पूरी तरह कैसे बच सकते हैं "

var foo = function () {
    var pub= { };
    return pub;
}
var bar = foo();

वैकल्पिक रूप से आप ऐसा कर सकते हैं:

function foo() { }
var bar = new foo();

लेकिन ऐसा करने से आप नए कीवर्ड और इस का उपयोग करने के लिए किसी को भूल जाने का जोखिम उठाते हैं ऑपरेटर सब फ़ुबर है। AFAIK को ऐसा करने का कोई फायदा नहीं है (इसके अलावा आप इसका इस्तेमाल करते हैं)।

दिन के अंत में: यह रक्षात्मक होने के बारे में है। क्या आप नए कथन का उपयोग कर सकते हैं? हाँ। क्या यह आपके कोड को अधिक खतरनाक बनाता है? हाँ।

यदि आपने कभी C ++ लिखा है, तो आप उन्हें हटाने के बाद NULL को पॉइंटर्स सेट करने के लिए यह एक समान है।


6
नहीं, "नए फू ()" के साथ कुछ गुण लौटे ऑब्जेक्ट पर सेट किए गए हैं, जैसे कंस्ट्रक्टर।
कुछ

34
तो, बस यह स्पष्ट करने के लिए: आपको "नया" का उपयोग नहीं करना चाहिए क्योंकि आप इसे भूल सकते हैं? तुम मजा़क कर रहे हो न?
बॉम्बे

16
@ बॉम्बे: अन्य भाषाओं में "नया" भूल जाने पर एक त्रुटि होगी। जावास्क्रिप्ट में, यह सिर्फ ट्रकिंग करता रहता है। आप भूल सकते हैं, और कभी महसूस नहीं कर सकते। और बस erroroneous कोड देख नहीं होते सब क्या गलत हो रहा पर स्पष्ट हो।
केंट फ्रेड्रिक

3
@Greg: मैं यह नहीं देखता कि पहली तकनीक प्रोटोटाइप चेन के उपयोग की अनुमति कैसे देती है - वस्तु शाब्दिक रूप से महान हैं, लेकिन प्रदर्शन से दिए गए प्रदर्शन और अन्य लाभ को डर के बाहर फेंकने से थोड़ा मूर्खतापूर्ण लगता है।
शोग

5
@ बॉम्बे - आपको "नया" का उपयोग करना चाहिए क्योंकि आप (और कोई भी जो आपके कोड का उपयोग करता है) कभी गलती नहीं करेगा? तुम मजा़क कर रहे हो न?
ग्रेग डीन

20

मुझे लगता है कि "नया" कोड में स्पष्टता जोड़ता है। और स्पष्टता सब कुछ के लायक है। यह जानने के लिए अच्छा है कि नुकसान हो रहे हैं, लेकिन स्पष्टता से परहेज करके उन्हें टालना मेरे लिए रास्ता नहीं लगता।


16

केस 1: newकी आवश्यकता नहीं है और इसे टाला जाना चाहिए

var str = new String('asd');  // type: object
var str = String('asd');      // type: string

var num = new Number(12);     // type: object
var num = Number(12);         // type: number

केस 2: newआवश्यक है, अन्यथा आपको एक त्रुटि मिलेगी

new Date().getFullYear();     // correct, returns the current year, i.e. 2010
Date().getFullYear();         // invalid, returns an error

5
यह ध्यान दिया जाना चाहिए कि 1 के मामले में, कंस्ट्रक्टर को एक फ़ंक्शन के रूप में कॉल करना केवल तभी समझ में आता है यदि आप प्रकार के रूपांतरण का इरादा कर रहे हैं (और यह नहीं जानते कि क्या हल ऑब्जेक्ट में रूपांतरण विधि है, जैसे कि toString())। अन्य सभी मामलों में, शाब्दिक का उपयोग करें। नहीं String('asd') , लेकिन बस 'asd', और नहीं Number(12) , बल्कि बस 12
पॉइंटएपर्स

1
@PointedEars इस नियम का एक अपवाद होगा Array: Array(5).fill(0) स्पष्ट रूप से अधिक पठनीय है [undefined, undefined, undefined, undefined, undefined].fill(0)और(var arr = []).length = 5; arr.fill(0);
yyny

@YoYoYonnY मेरा बयान उत्तर के मामले 1 के संदर्भ में किया गया था, जो newकि आदिम प्रकार के अनुरूप वस्तु प्रकारों के लिए निर्माणकर्ताओं के साथ उपयोग को संदर्भित करता है । आप जो शाब्दिक सुझाव दे रहे हैं वह कॉल (कोशिश ) के बराबर नहीं है , और बाकी एक वाक्यविन्यास त्रुटि है :) अन्यथा आप सही हैं, हालांकि यह भी ध्यान दिया जाना चाहिए कि यदि आप गैर-अनुरूपण कार्यान्वयन पर विचार करते हैं तो अस्पष्ट हो सकता है (और इसलिए एक अनुकरण किया )। Array0 in …Array(5) Array.prototype.fill(…)
प्वाइंटएडर्स

12

यहाँ संक्षिप्त सारांश है जिसे मैं प्रयोग करने के विरुद्ध और उसके विरुद्ध दो सबसे मजबूत तर्क दे सकता हूँ new ऑपरेटर :

के खिलाफ बहस new

  1. उपयोग किए गए ऑब्जेक्ट के रूप में त्वरित किए जाने वाले फ़ंक्शंस newऑपरेटर में विनाशकारी प्रभाव हो सकते हैं यदि वे सामान्य कार्यों के रूप में गलत तरीके से लगाए जाते हैं। इस तरह के एक मामले में एक फ़ंक्शन के कोड को उस क्षेत्र में निष्पादित किया जाएगा जहां कार्य को स्थानीय वस्तु के दायरे के बजाय फ़ंक्शन कहा जाता है। इससे वैश्विक चर और गुण विनाशकारी परिणामों के साथ ओवरराइट हो सकते हैं।
  2. अंत में, लिखना function Func(), और फिर कॉल करना Func.prototype और उसमें सामान जोड़ना ताकि आप new Func()अपनी वस्तु का निर्माण करने के लिए कॉल कर सकें कुछ प्रोग्रामर को बदसूरत लगता है, जो वास्तुशिल्प और शैलीगत कारणों के लिए वस्तु विरासत की एक और शैली का उपयोग करेंगे।

इस तर्क के बारे में अधिक जानने के लिए डगलस क्रॉकफोर्ड की महान और संक्षिप्त पुस्तक जावास्क्रिप्ट: द गुड पार्ट्स की जाँच करें। वास्तव में यह वैसे भी बाहर की जाँच करें।

के पक्ष में तर्क new

  1. newप्रोटोटाइप असाइनमेंट के साथ ऑपरेटर का उपयोग करना तेज है।
  2. वैश्विक नेमस्पेस में एक रचनाकार फ़ंक्शन के कोड को गलती से चलाने के बारे में सामान को आसानी से रोका जा सकता है, अगर आप हमेशा यह देखने के लिए कि क्या वे सही नहीं हैं, यह देखने के लिए अपने निर्माता कार्यों में थोड़ा सा कोड शामिल करें। , उचित रूप से कॉल को संभालना।

इस तकनीक की एक सरल व्याख्या के लिए जॉन रेजिग की पोस्ट देखें , और आमतौर पर अधिवक्ता मॉडल की गहन व्याख्या के लिए वह वकालत करता है।


तर्कों के खिलाफ एक अद्यतन: # 1 को 'use strict';मोड (या आपके लिंक में विधि) का उपयोग करके कम किया जा सकता है # 2 में ES6 में शक्करयुक्त चीनी है , हालांकि व्यवहार पहले जैसा ही है।
निनमोंकी

9

मैं यहाँ पेज़ और कुछ से सहमत हूँ।

मुझे यह स्पष्ट प्रतीत होता है कि "नया" स्व वर्णनात्मक वस्तु निर्माण है, जहां YUI पैटर्न ग्रेग डीन पूरी तरह से अस्पष्ट है

संभावना है कि कोई लिख सकता है var bar = foo;या var bar = baz();जहां बाज एक वस्तु बनाने की विधि नहीं है, कहीं अधिक खतरनाक है।


8

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

जावास्क्रिप्ट प्रोटोटाइप-आधारित ऑब्जेक्ट-ओरिएंटेड है। इसलिए प्रत्येक वस्तु को अन्य वस्तु से बनाया जाना चाहिए जैसे कि var newObj=Object.create(oldObj)। यहां पुराने ओओबीज को न्यूऑब्ज (इसलिए "प्रोटोटाइप-आधारित") का प्रोटोटाइप कहा जाता है । इसका तात्पर्य यह है कि अगर newObj में कोई प्रॉपर्टी नहीं पाई जाती है, तो उसे oldObj में खोजा जाएगा । newObj डिफ़ॉल्ट रूप से इस प्रकार एक खाली वस्तु होगी, लेकिन इसकी प्रोटोटाइप श्रृंखला के कारण इसमें पुराने मानों के सभी मान दिखाई देते हैं

दूसरी ओर यदि आप करते हैं var newObj=new oldObj(), तो newObj का प्रोटोटाइप पुराना Obj.prototype है , जिसे समझना अनावश्यक रूप से मुश्किल है।

चाल का उपयोग करना है

Object.create=function(proto){
  var F = function(){};
  F.prototype = proto;
  var instance = new F();
  return instance;
};

यह इस फंक्शन के अंदर है और केवल यहीं पर नए का उपयोग किया जाना चाहिए। इसके बाद बस Object.create () विधि का उपयोग करें । पद्धति प्रोटोटाइप समस्या का समाधान करती है।


7
सच कहूं तो, मैं इस तकनीक के बारे में जंगली नहीं हूं - यह कुछ भी नया नहीं करता है, और जैसा कि आपका जवाब दिखाता है कि यह एक बैसाखी भी हो सकता है। IMHO, प्रोटोटाइप जंजीरों और वस्तु तात्कालिकता को समझना जावास्क्रिप्ट को समझना महत्वपूर्ण है ... लेकिन अगर यह आपको उन्हें सीधे उपयोग करने के लिए असुविधाजनक बनाता है, तो कुछ विवरणों की देखभाल के लिए एक सहायक फ़ंक्शन का उपयोग करना ठीक है, इसलिए जब तक आपको याद है कि आप क्या कर रहे हैं करते हुए। FWIW: इस पर (कुछ अधिक उपयोगी) भिन्नता ECMAScript 5 वीं संस्करण का हिस्सा है। एसटीडी, और पहले से ही कुछ ब्राउज़रों में उपलब्ध है - इसलिए आपको सावधान रहना चाहिए कि इसे नेत्रहीन रूप से फिर से परिभाषित न करें!
शोग ९

BTW: मुझे यकीन नहीं है कि आपने यह CW क्यों बनाया है, लेकिन यदि आप इसे मेरे द्वारा किए गए प्रारूपण सुधारों के साथ फिर से पोस्ट करना चाहते हैं, तो उस चेकबॉक्स से बचने के लिए सावधान रहें ...
Shog9

2
अनावश्यक रूप से समझना मुश्किल है? var c = new Car()ऐसा करने के समान हैvar c = Object.create(Car.prototype); Car.call(c)
जुआन मेंडेस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.