क्या जेएस वस्तुओं को परिभाषित करने का इस तरह का कोई उद्देश्य है?


87

मैं कुछ विरासत कोड बनाए रख रहा हूं और मैंने देखा है कि वस्तुओं को परिभाषित करने के लिए निम्न पैटर्न का उपयोग किया जाता है:

var MyObject = {};

(function (root) {

    root.myFunction = function (foo) {
        //do something
    };

})(MyObject);

क्या इसका कोई उद्देश्य है? क्या यह सिर्फ निम्नलिखित करने के बराबर है?

var MyObject = {

    myFunction : function (foo) {
        //do something
    };

};

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

धन्यवाद!


1
आपके सटीक उदाहरण में कोई अंतर नहीं है। यदि आप इसका विस्तार करते हैं, तो अंतर हो सकता है लेकिन फिर अलग-अलग दृष्टिकोण भी होंगे जो कि खेलने के लिए भी आते हैं।
ट्रैविस जे

इससे कोई फर्क नहीं पड़ता है, वस्तुओं को बोलने के लिए एक संदर्भ की एक प्रति के रूप में पारित किया जाता है, इसलिए यहां तक ​​कि जब IIFE के अंदर myFunction को परिभाषित करता है, तो यह अभी भी इसके बाहर सुलभ है।
एडेनो

1
@adeneo इस उदाहरण के लिए नहीं, myFunctionस्वयं के बाहर परिभाषित कुछ चर का उपयोग कर सकता है जो बाहर से सुलभ नहीं होंगे। मेरा जवाब देखें
जुआन मेंडेस 20


जवाबों:


116

इसे मॉड्यूल पैटर्न http://toddmotto.com/mastering-the-module-pattern/ कहा जाता है

मुख्य कारण आपके लिए वास्तव में निजी तरीके और चर बनाना है। आपके मामले में, यह सार्थक नहीं है क्योंकि यह किसी भी कार्यान्वयन के विवरण को नहीं छिपा रहा है।

यहां एक उदाहरण है जहां यह मॉड्यूल पैटर्न का उपयोग करने के लिए समझ में आता है।

var MyNameSpace = {};

(function(ns){
    // The value variable is hidden from the outside world
    var value = 0;

    // So is this function
    function adder(num) {
       return num + 1;
    }

    ns.getNext = function () {
       return value = adder(value);
    }
})(MyNameSpace);

var id = MyNameSpace.getNext(); // 1
var otherId = MyNameSpace.getNext(); // 2
var otherId = MyNameSpace.getNext(); // 3

जबकि यदि आप सिर्फ एक सीधी वस्तु का उपयोग करते हैं, adderऔर valueसार्वजनिक हो जाएगा

var MyNameSpace = {
    value: 0,
    adder: function(num) {
       return num + 1;
    },
    getNext: function() {
       return this.value = this.adder(this.value);
    }
}

और आप इसे सामान की तरह करके तोड़ सकते हैं

MyNameSpace.getNext(); // 1
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 1 again
delete MyNameSpace.adder;
MyNameSpace.getNext(); // error undefined is not a function

लेकिन मॉड्यूल संस्करण के साथ

MyNameSpace.getNext(); // 1
 // Is not affecting the internal value, it's creating a new property
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 2, yessss
// Is not deleting anything
delete MyNameSpace.adder;
MyNameSpace.getNext(); // no problemo, outputs 3

2
यह वास्तव में इस सवाल का जवाब नहीं देता है कि दोनों विकल्पों में क्या अंतर है?

20
@torazaburo ओपी का उदाहरण एक अच्छा उदाहरण नहीं था, मैंने एक वास्तविक उदाहरण प्रदान किया है जो दिखाता है कि मॉड्यूल पैटर्न का उपयोग कब करना है।
जुआन मेंडेस

यह ns.getNext: function () {संकलन नहीं होगा।
दंडित करें

मुझे लगता है, अगर मुझे यकीन है कि इसे कैसे ठीक किया जाए। मुझे लगा कि रोकने के लिए कुछ निर्माण करना था delete MyNameSpace.getNext

2
@ पंडुंड जेएस का कंपाइलर नहीं है इसमें दुभाषिया है:)
मेंढ़क '

22

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

http://lupomontero.com/using-javascript-closures-to-create-private-scopes/

लेख से:

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



कोड:

var MyObject = {};

(function (root) {
    function myPrivateFunction() {
       return "I can only be called from within the closure";
    }

    root.myFunction = function (foo) {
        //do something
    };    

    myPrivateFunction(); // returns "I can only be called from within the closure"

})(MyObject);


myPrivateFunction(); // throws error - undefined is not a function

1
myFunctionदूसरे संस्करण में वैश्विक दायरे में नहीं है। उद्देश्य वास्तव में एक गुंजाइश प्रदान करना है जहां आंतरिक सहायक कार्यों को परिभाषित किया जा सकता है।
बरमार

myFunctionवैश्विक दायरे में है क्योंकि यह वैश्विक वस्तु के भीतर परिभाषित है myObject। दूसरे संस्करण में आवेदन में कोई अन्य कोड निष्पादित कर सकता है myFunction। पहले संस्करण में बंद होने के भीतर केवल कोड तक पहुंच हैmyFunction
जोनाथन क्रो

नहीं, myFunctionकेवल MyObject.myFunction()पहले संस्करण के रूप में ही निष्पादित किया जा सकता है ।
बरमार

@JonathanCrowe ओपी का उदाहरण एक अच्छा उदाहरण नहीं है, यह मॉड्यूल के अंदर सब कुछ उजागर कर रहा है, इसलिए हां, यह बाहर सुलभ हो रहा है। एक उपयोगी मॉड्यूल केस के लिए मेरा जवाब देखें
जुआन मेंडेस

@JuanMendes अच्छा बिंदु, ओपी का उदाहरण मॉड्यूल पैटर्न का एक बड़ा उपयोग नहीं है
जोनाथन क्रो

6

फायदे:

  1. निजी दायरे में चर बनाए रखता है।

  2. आप मौजूदा ऑब्जेक्ट की कार्यक्षमता का विस्तार कर सकते हैं।

  3. प्रदर्शन बढ़ाया जाता है।

मुझे लगता है कि उपरोक्त तीन सरल बिंदु उन नियमों का पालन करने के लिए पर्याप्त हैं। और इसे सरल रखने के लिए आंतरिक कार्यों को लिखने के अलावा कुछ भी नहीं है।


6

आपके द्वारा दिखाए जाने वाले विशेष मामले में, कार्यक्षमता या दृश्यता के मामले में कोई सार्थक अंतर नहीं है।

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

var MyObject = {};
(function(root) {
    var seconds_per_day = 24 * 60 * 60;   // <-- private variable
    root.myFunction = function(foo) {
        return seconds_per_day;
    };
})(MyObject);

यह seconds_per_dayहर बार फ़ंक्शन की गणना करने से बचता है, जबकि इसे वैश्विक दायरे को प्रदूषित करने से भी बचाता है ।

हालाँकि, वहाँ कुछ भी अनिवार्य रूप से अलग नहीं है और सिर्फ कह रहा है

var MyObject = function() {
    var seconds_per_day = 24 * 60 * 60;
    return {
        myFunction: function(foo) {
            return seconds_per_day;
        }
    };
}();

मूल कोडर ने ऑब्जेक्ट के सिंटैक्टिव / सिंटैक्स का उपयोग करके ऑब्जेक्ट में फ़ंक्शन जोड़ने में सक्षम होना पसंद किया है root.myFunction = function, बजाय ऑब्जेक्ट के सिंटैक्स /myFunction: function । लेकिन यह अंतर मुख्य रूप से प्राथमिकता का विषय है।

हालाँकि, मूल कोडर द्वारा ली गई संरचना का यह लाभ है कि गुण / विधियाँ आसानी से कोड में कहीं और जोड़ी जा सकती हैं:

var MyObject = {};
(function(root) {
    var seconds_per_day = 24 * 60 * 60;
    root.myFunction = function(foo) {
        return seconds_per_day;
    };
})(MyObject);

(function(root) {
    var another_private_variable = Math.pi;
    root.myFunction2 = function(bar) { };
})(MyObject);

नीचे पंक्ति, अगर आपको ज़रूरत नहीं है, तो इस दृष्टिकोण को अपनाने की कोई आवश्यकता नहीं है, लेकिन इसे बदलने की भी कोई आवश्यकता नहीं है, क्योंकि यह पूरी तरह से अच्छी तरह से काम करता है और वास्तव में इसके कुछ फायदे हैं।


6
  1. पहले पैटर्न का उपयोग एक मॉड्यूल के रूप में किया जा सकता है जो एक वस्तु लेता है और कुछ संशोधनों के साथ उस वस्तु को वापस करता है। दूसरे शब्दों में, आप इस तरह के मॉड्यूल को निम्न प्रकार से परिभाषित कर सकते हैं।

    var module = function (root) {
        root.myFunction = function (foo) {
            //do something
        };
    }
    

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

    var obj = {};
    module(obj);
    

    इसलिए एक फायदा इस मॉड्यूल की बाद में उपयोग के लिए पुन: प्रयोज्य हो सकता है।


  1. पहले पैटर्न में, आप अपने निजी सामान जैसे कि निजी संपत्तियों और विधियों को संग्रहीत करने के लिए एक निजी दायरे को परिभाषित कर सकते हैं । उदाहरण के लिए, इस स्निपेट पर विचार करें:

    (function (root) {
    
        // A private property
        var factor = 3;
    
        root.multiply = function (foo) {
            return foo * factor;
        };
    })(MyObject);
    

  1. इस पैटर्न का उपयोग सभी प्रकार की वस्तुओं जैसे कि सरणियों, वस्तु शाब्दिक, कार्यों के लिए एक विधि या संपत्ति जोड़ने के लिए किया जा सकता है।

    function sum(a, b) {
        return a + b;
    }
    
    (function (root) {
        // A private property
        var factor = 3;
        root.multiply = function (foo) {
            return foo * factor;
        };
    })(sum);
    
    console.log(sum(1, 2)); // 3
    console.log(sum.multiply(4)); // 12
    

मेरी राय में मुख्य लाभ दूसरा हो सकता है (निजी गुंजाइश बनाना)


5

यह पैटर्न एक गुंजाइश प्रदान करता है जिसमें आप ऐसे सहायक कार्यों को परिभाषित कर सकते हैं जो वैश्विक दायरे में दिखाई नहीं देते हैं:

(function (root) {

    function doFoo() { ... };

    root.myFunction = function (foo) {
        //do something
        doFoo();
        //do something else
    };

})(MyObject);

doFoo अनाम फ़ंक्शन के लिए स्थानीय है, इसे बाहर से संदर्भित नहीं किया जा सकता है।

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