जवाबों:
मूल अंतर यह है कि एक कंस्ट्रक्टर फ़ंक्शन का उपयोग newकीवर्ड के साथ किया जाता है (जिसके कारण जावास्क्रिप्ट स्वचालित रूप से एक नया ऑब्जेक्ट बनाने के लिए, thisउस ऑब्जेक्ट पर फ़ंक्शन के भीतर सेट होता है, और ऑब्जेक्ट वापस कर देता है):
var objFromConstructor = new ConstructorFunction();
एक फैक्ट्री फ़ंक्शन को "नियमित" फ़ंक्शन की तरह कहा जाता है:
var objFromFactory = factoryFunction();
लेकिन इसे "फ़ैक्टरी" मानने के लिए किसी वस्तु का नया उदाहरण वापस करने की आवश्यकता होगी: यदि आप इसे सिर्फ बूलियन या कुछ लौटाते हैं, तो आप इसे "फ़ैक्टरी" फ़ंक्शन नहीं कहेंगे। ऐसा अपने आप नहीं होता है new, लेकिन यह कुछ मामलों के लिए अधिक लचीलापन देता है।
वास्तव में सरल उदाहरण में ऊपर उल्लिखित कार्य कुछ इस तरह दिख सकते हैं:
function ConstructorFunction() {
this.someProp1 = "1";
this.someProp2 = "2";
}
ConstructorFunction.prototype.someMethod = function() { /* whatever */ };
function factoryFunction() {
var obj = {
someProp1 : "1",
someProp2 : "2",
someMethod: function() { /* whatever */ }
};
// other code to manipulate obj in some way here
return obj;
}
बेशक आप कारखाने के कार्यों को उस सरल उदाहरण की तुलना में बहुत अधिक जटिल बना सकते हैं।
फ़ैक्टरी फ़ंक्शंस का एक फ़ायदा यह है कि लौटाए जाने वाले ऑब्जेक्ट कुछ पैरामीटर के आधार पर कई अलग-अलग प्रकार के हो सकते हैं।
someMethodद्वारा लौटाए गए ऑब्जेक्ट्स के लिए शामिल नहीं है , और यही वह जगह है जहां यह थोड़ा धूमिल हो जाता है। फैक्ट्री फ़ंक्शन के अंदर, यदि कोई बस करता है var obj = { ... , someMethod: function() {}, ... }, तो वह प्रत्येक वस्तु को वापस लौटा देगा someMethodजिसकी एक अलग प्रति है जो कुछ ऐसा है जो हम नहीं चाहते हैं। यह वह जगह है जहाँ कारखाने के कार्य का उपयोग newऔर prototypeअंदर मदद मिलेगी।
newनिर्माण कार्य के साथ उपयोग करना भूल जाते हैं ; मैंने सोचा कि यह वह जगह है जहाँ किसी को निर्माण कार्यों को फैक्ट्री फ़ंक्शंस उदाहरण के साथ बदलने की आवश्यकता हो सकती है और जहाँ मुझे लगा कि उदाहरणों में स्थिरता की आवश्यकता है। वैसे भी, उत्तर पर्याप्त जानकारीपूर्ण है। यह सिर्फ एक बिंदु था जिसे मैं उठाना चाहता था, यह नहीं कि मैं किसी भी तरह से उत्तर की गुणवत्ता पर खींच रहा हूं।
newआंतरिक रूप से उपयोग कर सकते हैं , या Object.create()किसी विशिष्ट प्रोटोटाइप के साथ एक ऑब्जेक्ट बनाने के लिए उपयोग कर सकते हैं ।
अधिकांश पुस्तकें आपको कंस्ट्रक्टर का उपयोग करना सिखाती हैं और new
this नई वस्तु को संदर्भित करता है
कुछ लोग var myFoo = new Foo();पढ़ना पसंद करते हैं ।
इंस्टेंटेशन का विवरण कॉलिंग एपीआई ( newआवश्यकता के माध्यम से ) में लीक हो जाता है , इसलिए सभी कॉलर्स को कंस्ट्रक्टर कार्यान्वयन के लिए कसकर जोड़ा जाता है। यदि आपको कभी भी कारखाने के अतिरिक्त लचीलेपन की आवश्यकता होती है, तो आपको सभी कॉलर्स (नियम के बजाय असाधारण रूप से असाधारण मामला) को रिफ्लेक्टर करना होगा।
भूल newइस तरह के एक सामान्य बग है, आपको यह सुनिश्चित करने के लिए बॉयलरप्लेट की जांच को जोड़ने पर जोर देना चाहिए कि कंस्ट्रक्टर को सही तरीके से कहा जाता है ( if (!(this instanceof Foo)) { return new Foo() })। EDIT: ES6 (ES2015) के बाद से आप newएक classकंस्ट्रक्टर के साथ भूल नहीं सकते हैं , या कंस्ट्रक्टर एक त्रुटि को फेंक देगा।
यदि आप instanceofजांच करते हैं, तो यह अस्पष्टता छोड़ देता है कि क्या newआवश्यक है या नहीं । मेरी राय में, यह नहीं होना चाहिए। आपने newआवश्यकता को प्रभावी ढंग से कम कर दिया है , जिसका अर्थ है कि आप ड्राबैक # 1 मिटा सकते हैं। लेकिन तब आपको अतिरिक्त बॉयलरप्लेट, एक कैपिटल लेटर, और कम लचीले thisसंदर्भ के साथ सिर्फ एक फैक्ट्री फंक्शन मिला है ।
लेकिन मेरी मुख्य चिंता यह है कि यह खुले / बंद सिद्धांत का उल्लंघन करता है। आप एक कंस्ट्रक्टर का निर्यात शुरू करते हैं, उपयोगकर्ता कंस्ट्रक्टर का उपयोग करना शुरू कर देते हैं, फिर सड़क के नीचे आपको एहसास होता है कि आपको किसी फैक्ट्री के लचीलेपन की आवश्यकता है, इसके बजाय, ऑब्जेक्ट पूल का उपयोग करने के लिए कार्यान्वयन को स्विच करने के लिए, या निष्पादन संदर्भों को पार करने के लिए या प्रोटोटाइप ओओ का उपयोग करके अधिक वंशानुक्रम लचीलापन है)।
हालांकि आप फंस गए हैं। आप अपने कंस्ट्रक्टर के साथ कॉल करने वाले सभी कोड को तोड़े बिना बदलाव नहीं कर सकते new। आप उदाहरण के लिए, प्रदर्शन लाभ के लिए ऑब्जेक्ट पूल का उपयोग करने के लिए स्विच नहीं कर सकते।
इसके अलावा, कंस्ट्रक्टरों का उपयोग आपको एक भ्रामक देता है instanceofजो निष्पादन संदर्भों में काम नहीं करता है, और यह काम नहीं करता है यदि आपका निर्माता प्रोटोटाइप बाहर हो जाता है। यह भी विफल हो जाएगा यदि आप thisअपने निर्माता से वापस लौटना शुरू करते हैं , और फिर एक मनमानी वस्तु निर्यात करने के लिए स्विच करते हैं, जो आपको अपने निर्माता में कारखाने की तरह व्यवहार को सक्षम करने के लिए करना होगा।
कम कोड - कोई बॉयलरप्लेट आवश्यक नहीं है।
आप किसी भी मनमानी वस्तु को वापस कर सकते हैं, और किसी भी मनमाने ढंग से प्रोटोटाइप का उपयोग कर सकते हैं - आपको विभिन्न प्रकार की वस्तुओं को बनाने के लिए अधिक लचीलापन देता है जो एक ही एपीआई को लागू करते हैं। उदाहरण के लिए, एक मीडिया प्लेयर जो एचटीएमएल 5 और फ्लैश प्लेयर, या एक इवेंट लाइब्रेरी दोनों का उदाहरण बना सकता है, जो डोम इवेंट्स या वेब सॉकेट इवेंट्स का उत्सर्जन कर सकता है। फैक्ट्रियां निष्पादन के संदर्भों में वस्तुओं को तुरंत रोक सकती हैं, ऑब्जेक्ट पूल का लाभ उठा सकती हैं, और अधिक लचीले प्रोटोटाइप के उत्तराधिकार मॉडल के लिए अनुमति दे सकती हैं।
आपको कभी भी एक कारखाने से एक कंस्ट्रक्टर में बदलने की आवश्यकता नहीं होगी, इसलिए रिफैक्टिंग एक मुद्दा कभी नहीं होगा।
उपयोग करने के बारे में कोई अस्पष्टता नहीं new। मत करो। (यह thisबुरा व्यवहार करेगा , अगले बिंदु देखें)।
thisसामान्य रूप से ऐसा व्यवहार करता है - इसलिए आप इसका उपयोग मूल वस्तु तक पहुंचने के लिए कर सकते हैं (उदाहरण के लिए, अंदर player.create(), thisसंदर्भित करता है player, ठीक उसी तरह जैसे कोई अन्य विधि मंगलाचरण होगा। callऔर साथ applyही पुन: असाइन करें this, जैसा कि अपेक्षित है। यदि आप मूल ऑब्जेक्ट पर प्रोटोटाइप स्टोर करते हैं, तो। गतिशील रूप से कार्यक्षमता की अदला-बदली करने का एक शानदार तरीका हो सकता है, और अपनी वस्तु की तात्कालिकता के लिए बहुत लचीले बहुरूपता को सक्षम कर सकता है।
पूंजी लगाना या नहीं, इसके बारे में कोई अस्पष्टता नहीं। मत करो। लिंट उपकरण शिकायत करेंगे, और फिर आप का उपयोग करने की कोशिश newकरेंगे, और फिर आप ऊपर वर्णित लाभ को पूर्ववत करेंगे।
कुछ लोगों को रास्ता पसंद है var myFoo = foo();या var myFoo = foo.create();पढ़ता है।
newअपेक्षानुसार व्यवहार नहीं करता (ऊपर देखें)। समाधान: इसका उपयोग न करें।
thisनई वस्तु का उल्लेख नहीं करता (बजाय, अगर निर्माता डॉट नोटेशन या वर्ग कोष्ठक अंकन, जैसे foo.bar () के साथ शुरू हो जाती है - thisको संदर्भित करता है fooहर दूसरे JavaScript विधि की तरह - - लाभ देखें)।
newखुले / बंद सिद्धांत का उल्लंघन करता है। इन टिप्पणियों की अनुमति की तुलना में बहुत बड़ी चर्चा के लिए मध्यम.com/javascript-scene/… देखें ।
newकीवर्ड के बिना ऐसा करते हैं , मुझे विश्वास नहीं होता कि newकीवर्ड वास्तव में कोई अतिरिक्त पठनीयता प्रदान करता है। IMO, कॉलर्स को अधिक टाइप करने में सक्षम करने के लिए हुप्स के माध्यम से कूदना मूर्खतापूर्ण लगता है।
एक कंस्ट्रक्टर उस वर्ग का एक उदाहरण देता है जिसे आप इसे कहते हैं। एक फैक्ट्री फ़ंक्शन कुछ भी वापस कर सकता है। जब आप मनमाना मूल्यों को वापस करने की आवश्यकता होती है या जब किसी वर्ग की बड़ी सेटअप प्रक्रिया होती है, तो आप फ़ैक्टरी फ़ंक्शन का उपयोग करेंगे।
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
newएक वस्तु बनाता है पर प्रोटोटाइप बनाया और उसके मूल्य के रूप में बनाया वस्तु के साथ User.prototypeकहता है ।Userthis
new वैकल्पिक के रूप में अपने ऑपरेंड के लिए एक तर्क अभिव्यक्ति का व्यवहार करता है:
let user = new User;
कोई तर्क के साथ newकॉल करने का कारण होगा User।
newबनाई गई वस्तु को तब तक लौटाता है , जब तक कि निर्माता वस्तु का मूल्य नहीं लौटाता है , जो बदले में लौटा दिया जाता है। यह एक किनारे का मामला है जिसे अधिकांश भाग के लिए नजरअंदाज किया जा सकता है।
कंस्ट्रक्टर फ़ंक्शन द्वारा बनाई गई ऑब्जेक्ट्स कंस्ट्रक्टर की prototypeसंपत्ति से गुण प्राप्त करती हैं, और instanceOfनिर्माता फ़ंक्शन पर ऑपरेटर का उपयोग करके सही लौटाता है ।
उपरोक्त व्यवहार विफल हो सकते हैं यदि आप prototypeपहले से ही कंस्ट्रक्टर का उपयोग करने के बाद विधायक की संपत्ति के मूल्य को गतिशील रूप से बदलते हैं। ऐसा करना दुर्लभ है , और यदि classकीवर्ड का उपयोग करके निर्माणकर्ता बनाया गया था तो इसे बदला नहीं जा सकता है ।
extendsकीवर्ड का उपयोग करके कंस्ट्रक्टर कार्यों को बढ़ाया जा सकता है ।
कन्स्ट्रक्टर फ़ंक्शंस nullत्रुटि मान के रूप में वापस नहीं आ सकते । चूंकि यह ऑब्जेक्ट डेटा प्रकार नहीं है, इसलिए इसे अनदेखा कर दिया जाता है new।
function User(name, age) {
return {
name,
age,
}
};
let user = User("Tom", 23);
यहां फैक्ट्री फ़ंक्शन को बिना बुलाया जाता है new। यह फ़ंक्शन प्रत्यक्ष या अप्रत्यक्ष उपयोग के लिए पूरी तरह से जिम्मेदार है यदि इसके तर्क और वस्तु का प्रकार यह वापस आ जाता है। इस उदाहरण में यह तर्कों से निर्धारित कुछ गुणों के साथ एक सरल [वस्तु वस्तु] देता है।
आसानी से कॉलर से ऑब्जेक्ट निर्माण के कार्यान्वयन की जटिलताओं को छुपाता है। यह ब्राउज़र में मूल कोड फ़ंक्शन के लिए विशेष रूप से उपयोगी है।
फ़ैक्टरी फ़ंक्शन को हमेशा एक ही प्रकार की वस्तुओं को वापस करने की आवश्यकता नहीं होती है, और यहां तक कि nullत्रुटि संकेतक के रूप में भी लौट सकते हैं ।
सरल मामलों में, कारखाने के कार्य संरचना और अर्थ में सरल हो सकते हैं।
आमतौर पर लौटे ऑब्जेक्ट फैक्ट्री फ़ंक्शन की prototypeसंपत्ति से विरासत में नहीं मिलते हैं, और से लौटते falseहैं instanceOf factoryFunction।
फैक्ट्री फ़ंक्शन को extendsकीवर्ड का उपयोग करके सुरक्षित रूप से विस्तारित नहीं किया जा सकता है, क्योंकि फैक्ट्री फ़ंक्शन द्वारा उपयोग किए गए कंस्ट्रक्टर prototypeकी prototypeसंपत्ति के बजाय विस्तारित ऑब्जेक्ट फैक्ट्री फ़ंक्शंस प्रॉपर्टी से वारिस होंगे ।
फैक्टरियां हमेशा "बेहतर" होती हैं। तब ऑब्जेक्ट ओरिएंटेड भाषाओं का उपयोग करते हुए
कार्यान्वयन (नए के साथ बनाई गई वास्तविक वस्तुएं) कारखाने उपयोगकर्ता / उपभोक्ता के संपर्क में नहीं हैं। इसका मतलब यह है कि जब तक वह अनुबंध को नहीं तोड़ता है, तब तक कारखाना डेवलपर नए कार्यान्वयन का विस्तार और निर्माण कर सकता है ... और यह कारखाना उपभोक्ता को अपने कोड को बदलने के बिना नए एपीआई से लाभ उठाने की अनुमति देता है ... अगर उन्होंने नया प्रयोग किया और एक "नया" कार्यान्वयन साथ आता है, तो उन्हें हर पंक्ति को बदलना होगा जो "नया" का उपयोग करता है "नया" कार्यान्वयन का उपयोग करने के लिए ... कारखाने के साथ उनका कोड नहीं बदलता है ...
फैक्टरियां - बाकी सभी चीज़ों से बेहतर - वसंत की रूपरेखा पूरी तरह से इस विचार के आसपास बनाई गई है।
फैक्ट्रियां अमूर्तता की एक परत हैं, और सभी अमूर्तों की तरह उनमें जटिलता भी है। एक कारखाने आधारित एपीआई का सामना करते समय यह पता लगाना कि किसी दिए गए एपीआई के लिए कारखाना क्या है, एपीआई उपभोक्ता के लिए चुनौतीपूर्ण हो सकता है। कंस्ट्रक्टर्स के साथ खोजनीयता तुच्छ है।
जब आप कॉटर्स और कारखानों के बीच निर्णय लेते हैं, तो आपको यह तय करने की आवश्यकता होती है कि क्या जटिलता लाभ द्वारा उचित है।
इस बात पर ध्यान देने की आवश्यकता नहीं है कि जावास्क्रिप्ट निर्माण करने वाले इस या अपरिभाषित के अलावा कुछ और लौटाकर मनमाने कारखाने बना सकते हैं। तो js में आप दोनों दुनिया के सबसे अच्छे - खोज योग्य एपीआई और ऑब्जेक्ट पूलिंग / कैशिंग प्राप्त कर सकते हैं।
new, व्यवहार में परिवर्तन this, रिटर्न वैल्यू को बदलना, एक प्रोटोटाइप रेफ को कनेक्ट करना, सक्षम करना instanceof(जो झूठ है और इस उद्देश्य के लिए इसका उपयोग नहीं किया जाना चाहिए)। मूल रूप से, वे सभी "सुविधाएँ" हैं। व्यवहार में, वे आपके कोड की गुणवत्ता पर चोट करते हैं।