जावास्क्रिप्ट में कार्यों को कैसे अधिभारित करें?


103

ओवरलोडिंग के लिए शास्त्रीय (गैर-जेएस) दृष्टिकोण:

function myFunc(){
 //code
}

function myFunc(overloaded){
 //other code
}

एक से अधिक फ़ंक्शन को एक ही नाम से परिभाषित नहीं किया जाना चाहिए। इस प्रकार, इस तरह की चीजें दिखाई देती हैं:

function myFunc(options){
 if(options["overloaded"]){
  //code
 }
}

क्या किसी ऑब्जेक्ट को ओवरलोड के साथ पास करने के अलावा जावास्क्रिप्ट में फ़ंक्शन ओवरलोडिंग के लिए बेहतर वर्कअराउंड है?

ओवरलोड में गुजरना जल्दी से एक फ़ंक्शन का कारण बन सकता है क्योंकि बहुत संभव है क्योंकि प्रत्येक संभावित अधिभार को तब सशर्त बयान की आवश्यकता होगी। //codeउन सशर्त बयानों के अंदर को पूरा करने के लिए कार्यों का उपयोग करना स्कोप्स के साथ मुश्किल परिस्थितियों का कारण बन सकता है।


1
तब आप जावास्क्रिप्ट के बारे में गलत सोच रहे हैं; यदि आपके पास अधिभार और गुंजाइश के साथ मुद्दे हैं, तो आपको शायद एक अलग विधि का नाम होना चाहिए क्योंकि ऐसा लगता है कि यह एक और काम कर रहा है
joshcomley

@joshcomley - ओवरलोड और स्कोप को संभालने के लिए कोड की आवश्यकता होती है। मैं केवल यह सुनिश्चित करने की कोशिश कर रहा हूं कि जिस कोड का मैं उपयोग कर रहा हूं, वह यथासंभव कुशल हो। वर्कअराउंड के साथ स्कोप को संभालना ठीक है, लेकिन मैं कम से कम सर्वोत्तम अभ्यास विधियों का उपयोग करने की कोशिश करता हूं।
ट्रैविस जे

जवाबों:


126

जावास्क्रिप्ट में ओवरलोडिंग पर बहस करने के लिए कई पहलू हैं:

  1. परिवर्तनीय तर्क - आप विभिन्न प्रकार के तर्कों को पारित कर सकते हैं (प्रकार और मात्रा दोनों में) और फ़ंक्शन इस तरीके से व्यवहार करेगा जो उससे पारित तर्कों से मेल खाता है।

  2. डिफ़ॉल्ट तर्क - आप एक तर्क के लिए एक डिफ़ॉल्ट मान को परिभाषित कर सकते हैं यदि यह पारित नहीं हुआ है।

  3. नामित तर्क - तर्क आदेश अप्रासंगिक हो जाता है और आप सिर्फ नाम लेते हैं जो आप फ़ंक्शन में पास करना चाहते हैं।

नीचे तर्क हैंडलिंग की इन श्रेणियों में से प्रत्येक पर एक खंड है।

परिवर्तनीय तर्क

क्‍योंकि जावास्क्रिप्ट में तर्कों पर किसी प्रकार की जाँच नहीं है या तर्कों की आवश्‍यकता नहीं है, तो आपके पास इसका एक ही कार्यान्वयन myFunc()हो सकता है कि तर्कों, प्रकारों या तर्कों की जाँच करके इस पर तर्क दिया जा सकता है।

jQuery हर समय ऐसा करता है। आप कुछ तर्कों को वैकल्पिक बना सकते हैं या आप अपने कार्य में इस बात के आधार पर शाखा लगा सकते हैं कि क्या तर्क दिए गए हैं।

इन प्रकार के अधिभार को लागू करने में, आपके पास कई अलग-अलग तकनीकें हैं जिनका आप उपयोग कर सकते हैं:

  1. आप किसी भी दिए गए तर्क की उपस्थिति के लिए जाँच करके देख सकते हैं कि घोषित तर्क नाम मान है या नहीं undefined
  2. आप के साथ कुल मात्रा या तर्क की जाँच कर सकते हैं arguments.length
  3. आप किसी भी दिए गए तर्क के प्रकार की जांच कर सकते हैं।
  4. तर्कों की चर संख्याओं के लिए, आप argumentsकिसी भी दिए गए तर्क तक पहुँचने के लिए छद्म-सरणी का उपयोग कर सकते हैं arguments[i]

यहाँ कुछ उदाहरण हैं:

आइए देखें jQuery की obj.data()विधि। यह उपयोग के चार विभिन्न रूपों का समर्थन करता है:

obj.data("key");
obj.data("key", value);
obj.data();
obj.data(object);

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

यहां बताया गया है कि अंग्रेजी में इन सभी विकल्पों में से कोई एक कैसे समझ सकता है और फिर मैं उन सभी को कोड में संयोजित करूंगा:

// get the data element associated with a particular key value
obj.data("key");

यदि पहला तर्क पास हो गया .data()है और दूसरा तर्क है undefined, तो कॉलर को इस फॉर्म का उपयोग करना होगा।


// set the value associated with a particular key
obj.data("key", value);

यदि दूसरा तर्क अपरिभाषित नहीं है, तो किसी विशेष कुंजी का मान सेट करें।


// get all keys/values
obj.data();

यदि कोई तर्क पारित नहीं होता है, तो लौटे हुए ऑब्जेक्ट में सभी कुंजी / मान लौटाएं।


// set all keys/values from the passed in object
obj.data(object);

यदि पहले तर्क का प्रकार एक सादा वस्तु है, तो उस ऑब्जेक्ट से सभी कुंजी / मान सेट करें।


यहां बताया गया है कि आप उन सभी को जावास्क्रिप्ट लॉजिक के एक सेट में कैसे जोड़ सकते हैं:

 // method declaration for .data()
 data: function(key, value) {
     if (arguments.length === 0) {
         // .data()
         // no args passed, return all keys/values in an object
     } else if (typeof key === "string") {
         // first arg is a string, look at type of second arg
         if (typeof value !== "undefined") {
             // .data("key", value)
             // set the value for a particular key
         } else {
             // .data("key")
             // retrieve a value for a key
         }
     } else if (typeof key === "object") {
         // .data(object)
         // set all key/value pairs from this object
     } else {
         // unsupported arguments passed
     }
 },

इस तकनीक की कुंजी यह सुनिश्चित करना है कि आपके द्वारा स्वीकार किए जाने वाले सभी प्रकार के तर्क विशिष्ट रूप से पहचाने जाने योग्य हैं और इस बात को लेकर कोई भ्रम नहीं है कि कॉलर किस फॉर्म का उपयोग कर रहा है। इसके लिए आमतौर पर तर्कों को उचित रूप से क्रमबद्ध करने की आवश्यकता होती है और यह सुनिश्चित करना होता है कि तर्कों के प्रकार और स्थिति में पर्याप्त विशिष्टता है कि आप हमेशा बता सकें कि किस फॉर्म का उपयोग किया जा रहा है।

उदाहरण के लिए, यदि आपके पास एक फ़ंक्शन है जो तीन स्ट्रिंग तर्क लेता है:

obj.query("firstArg", "secondArg", "thirdArg");

आप तीसरे तर्क को आसानी से वैकल्पिक बना सकते हैं और आप आसानी से उस स्थिति का पता लगा सकते हैं, लेकिन आप केवल दूसरे तर्क को वैकल्पिक नहीं बना सकते हैं क्योंकि आप यह नहीं बता सकते हैं कि इनमें से किस कॉलर के पास होने का अर्थ है क्योंकि दूसरे की पहचान करने का कोई तरीका नहीं है तर्क का अर्थ दूसरा तर्क है या दूसरे तर्क को छोड़ दिया गया था, इसलिए दूसरे तर्क के स्थान पर वास्तव में तीसरा तर्क क्या है:

obj.query("firstArg", "secondArg");
obj.query("firstArg", "thirdArg");

चूंकि सभी तीन तर्क एक ही प्रकार के हैं, इसलिए आप विभिन्न तर्कों के बीच अंतर नहीं बता सकते हैं ताकि आपको पता न चले कि कॉलर का क्या इरादा है। इस कॉलिंग शैली के साथ, केवल तीसरा तर्क वैकल्पिक हो सकता है। यदि आप दूसरे तर्क को छोड़ना चाहते हैं, तो इसे null(या कुछ अन्य पता लगाने योग्य मूल्य) के बजाय पास करना होगा और आपका कोड पता लगाएगा:

obj.query("firstArg", null, "thirdArg");

यहाँ वैकल्पिक तर्क का एक jQuery उदाहरण है। दोनों तर्क वैकल्पिक हैं और पारित नहीं होने पर डिफ़ॉल्ट मान लेते हैं:

clone: function( dataAndEvents, deepDataAndEvents ) {
    dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
    deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

    return this.map( function () {
        return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
    });
},

यहां एक jQuery का उदाहरण दिया गया है जहां तर्क गायब हो सकता है या तीन अलग-अलग प्रकारों में से कोई एक हो सकता है जो आपको चार अलग-अलग अधिभार देता है:

html: function( value ) {
    if ( value === undefined ) {
        return this[0] && this[0].nodeType === 1 ?
            this[0].innerHTML.replace(rinlinejQuery, "") :
            null;

    // See if we can take a shortcut and just use innerHTML
    } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
        (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
        !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

        value = value.replace(rxhtmlTag, "<$1></$2>");

        try {
            for ( var i = 0, l = this.length; i < l; i++ ) {
                // Remove element nodes and prevent memory leaks
                if ( this[i].nodeType === 1 ) {
                    jQuery.cleanData( this[i].getElementsByTagName("*") );
                    this[i].innerHTML = value;
                }
            }

        // If using innerHTML throws an exception, use the fallback method
        } catch(e) {
            this.empty().append( value );
        }

    } else if ( jQuery.isFunction( value ) ) {
        this.each(function(i){
            var self = jQuery( this );

            self.html( value.call(this, i, self.html()) );
        });

    } else {
        this.empty().append( value );
    }

    return this;
},

नामित तर्क

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

यहाँ एक सरल ES5 उदाहरण दिया गया है:

jQuery का $.ajax()एक प्रकार का उपयोग स्वीकार करता है जहां आप इसे एक एकल पैरामीटर पास करते हैं जो गुणों और मूल्यों के साथ एक नियमित जावास्क्रिप्ट ऑब्जेक्ट है। आप कौन से गुण पास करते हैं यह निर्धारित करते हैं कि कौन से तर्क / विकल्प अजाक्स कॉल में पारित किए जा रहे हैं। कुछ की आवश्यकता हो सकती है, कई वैकल्पिक हैं। चूंकि वे एक वस्तु पर गुण हैं, इसलिए कोई विशिष्ट आदेश नहीं है। वास्तव में, 30 से अधिक विभिन्न गुण हैं जो उस वस्तु पर पारित किए जा सकते हैं, केवल एक (url) की आवश्यकता है।

यहाँ एक उदाहरण है:

$.ajax({url: "http://www.example.com/somepath", data: myArgs, dataType: "json"}).then(function(result) {
    // process result here
});

$.ajax()कार्यान्वयन के अंदर , यह केवल पूछताछ कर सकता है कि आने वाली वस्तु पर कौन से गुण पारित किए गए थे और नामित तर्क के रूप में उपयोग करते हैं। यह या तो के साथ for (prop in obj)या Object.keys(obj)उसके बाद एक सरणी में सभी गुणों को प्राप्त करके किया जा सकता है ।

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

ES6 वातावरण में, उपरोक्त पारित ऑब्जेक्ट के लिए डिफ़ॉल्ट गुण / मान बनाने के लिए विनाशकारी का उपयोग करना संभव है। इस संदर्भ लेख में इस पर अधिक विस्तार से चर्चा की गई है ।

यहाँ उस लेख से एक उदाहरण है:

function selectEntries({ start=0, end=-1, step=1 } = {}) {
    ···
};

यह डिफ़ॉल्ट गुण और मान के लिए मान बनाता है start, endऔर फ़ंक्शन पर stepपारित ऑब्जेक्ट पर गुण selectEntries()

फ़ंक्शन तर्क के लिए डिफ़ॉल्ट मान

ES6 में, जावास्क्रिप्ट तर्कों के लिए डिफ़ॉल्ट मानों के लिए अंतर्निहित भाषा समर्थन जोड़ता है।

उदाहरण के लिए:

function multiply(a, b = 1) {
  return a*b;
}

multiply(5); // 5

एमडीएन पर यहां इस्तेमाल किए जा सकने वाले तरीकों का और वर्णन ।


तो मुझे बस एक अनुकूलनीय फ़ंक्शन के साथ रहना चाहिए और स्वीकार करना चाहिए कि फ़ंक्शन ओवरलोड मुखौटा को लागू करने के लिए सबसे अच्छा अभ्यास?
ट्रैविस जे

2
@TravisJ - हाँ, अनुकूलनीय कार्य वह तरीका है जो ओवरस्क्रिप्ट जावस्क्रिप्ट में किया जाता है। आपका दूसरा विकल्प अलग-अलग तर्कों के साथ एक अलग नाम वाले फ़ंक्शन का उपयोग करना है। यदि दो कार्यान्वयन में कुछ भी सामान्य नहीं है, तो या तो एक स्वीकार्य अभ्यास है। यदि दो कार्यान्वयन अनिवार्य रूप से एक ही काम कर रहे हैं, लेकिन बस अलग-अलग तर्कों के साथ शुरू होता है, तो मुझे लगता है कि यह आपके इंटरफ़ेस को अनुकूलनीय फ़ंक्शन का उपयोग करने के लिए अधिक कॉम्पैक्ट बनाता है और यह आपको दो संबंधित कार्यान्वयनों के बीच कोड साझा करने का अवसर देता है।

कुछ कोड उदाहरण जोड़े गए, अंग्रेजी और वास्तविक कोड दोनों में समझाया गया।
jfriend00

जब मैं यह कोशिश करता हूं, तो मुझे सफारी के नवीनतम संस्करण में एक त्रुटि, अप्रत्याशित टोकन '=' मिल रहा है resetProgressBar: function(display_errors, lockout = false)
निक

@ निक - इस ES6 संगतता तालिका के अनुसार , डिफ़ॉल्ट पैरामीटर मान सफारी 10 और बाद में काम करना चाहिए। प्रति इस MDN पेज , यह "कोई समर्थन नहीं" सफारी में कहते हैं। मेरे पास मैक नहीं है इसलिए मैं इसे खुद नहीं परख सकता। ऐसा लगता है कि आम तौर पर कई ब्राउज़रों में बाद में कार्यान्वित ES6 सुविधाओं में से एक है। उदाहरण के लिए, यह iOS9 में अभी तक ऐसा नहीं दिखता है।
९'१६

33

जावास्क्रिप्ट में एक फ़ंक्शन को ओवरलोड करना कई तरीकों से किया जा सकता है। उन सभी में एकल मास्टर फ़ंक्शन शामिल होता है जो या तो सभी प्रक्रियाओं को करता है, या उप-कार्यों / प्रक्रियाओं को दर्शाता है।

सबसे सामान्य सरल तकनीकों में से एक सरल स्विच शामिल है:

function foo(a, b) {
    switch (arguments.length) {
    case 0:
        //do basic code
        break;
    case 1:
        //do code with `a`
        break;
    case 2:
    default:
        //do code with `a` & `b`
        break;
    }
}

यदि आप ओवरलोड के लिए ओवरलोड नहीं बना रहे हैं, तो एक अधिक सुरुचिपूर्ण तकनीक एक सरणी (या ऑब्जेक्ट) का उपयोग करना होगा हर तर्क संख्या के ):

fooArr = [
    function () {
    },
    function (a) {
    },
    function (a,b) {
    }
];
function foo(a, b) {
    return fooArr[arguments.length](a, b);
}

यह पिछला उदाहरण बहुत सुरुचिपूर्ण नहीं है, कोई भी संशोधित कर सकता है fooArr , और यदि कोई व्यक्ति 2 से अधिक तर्कों में गुजरता है foo, तो यह विफल हो जाएगा , इसलिए एक बेहतर रूप मॉड्यूल पैटर्न और कुछ जांचों का उपयोग करना होगा:

var foo = (function () {
    var fns;
    fns = [
        function () {
        },
        function (a) {
        },
        function (a, b) {
        }
    ];
    function foo(a, b) {
        var fnIndex;
        fnIndex = arguments.length;
        if (fnIndex > foo.length) {
            fnIndex = foo.length;
        }
        return fns[fnIndex].call(this, a, b);
    }
    return foo;
}());

बेशक आपके अधिभार मापदंडों की एक गतिशील संख्या का उपयोग करना चाहते हैं, तो आप के लिए एक वस्तु का उपयोग कर सकते हैं fns संग्रह के ।

var foo = (function () {
    var fns;
    fns = {};
    fns[0] = function () {
    };
    fns[1] = function (a) {
    };
    fns[2] = function (a, b) {
    };
    fns.params = function (a, b /*, params */) {
    };
    function foo(a, b) {
        var fnIndex;
        fnIndex = arguments.length;
        if (fnIndex > foo.length) {
            fnIndex = 'params';
        }
        return fns[fnIndex].apply(this, Array.prototype.slice.call(arguments));
    }
    return foo;
}());

मेरी व्यक्तिगत पसंद है switch, हालांकि यह मास्टर फ़ंक्शन को बड़ा करता है। मैं इस तकनीक का उपयोग कहां करूंगा इसका एक सामान्य उदाहरण एक अभिगमक / उत्परिवर्ती विधि होगी:

function Foo() {} //constructor
Foo.prototype = {
    bar: function (val) {
        switch (arguments.length) {
        case 0:
            return this._bar;
        case 1:
            this._bar = val;
            return this;
        }
    }
}

यह एक वैकल्पिक का एक अच्छा उदाहरण है :)
ट्रैविस जे

1
अच्छा लगा, मुझे वह दूसरी तकनीक पसंद है
निक रोलैंडो

8

आप सख्त अर्थों में विधि अधिभार नहीं कर सकते। जिस तरह से यह में समर्थित है javaया नहीं है c#

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

जिस तरह से मुझे लगता है कि अधिकांश मामले के लिए उपयुक्त है, उनमें से एक है -

कहते हैं कि आपके पास तरीका है

function foo(x)
{
} 

ओवरलोडिंग विधि के बजाय जो जावास्क्रिप्ट में संभव नहीं है आप एक नई विधि को परिभाषित कर सकते हैं

fooNew(x,y,z)
{
}

और फिर 1 फ़ंक्शन को निम्नानुसार संशोधित करें -

function foo(x)
{
  if(arguments.length==2)
  {
     return fooNew(arguments[0],  arguments[1]);
  }
} 

यदि आपके पास कई ऐसे ओवरलोड विधि हैं, switchतो केवल if-elseबयानों की तुलना में उपयोग करने पर विचार करें ।

( अधिक विवरण ) PS: उपरोक्त लिंक मेरे व्यक्तिगत ब्लॉग पर जाता है, जिसमें इस पर अतिरिक्त विवरण है।


यह एक मुद्दा नहीं है, यह एक विशेषता है।
inetphantom

4

मैं तर्क संख्या के आधार पर थोड़ा अलग ओवरलोडिंग दृष्टिकोण का उपयोग कर रहा हूं। हालांकि मेरा मानना ​​है कि जॉन फॉसेट का दृष्टिकोण भी अच्छा है। यहाँ उदाहरण, जॉन रेजिग (jQuery के लेखक) स्पष्टीकरण पर आधारित कोड।

// o = existing object, n = function name, f = function.
    function overload(o, n, f){
        var old = o[n];
        o[n] = function(){
            if(f.length == arguments.length){
                return f.apply(this, arguments);
            }
            else if(typeof o == 'function'){
                return old.apply(this, arguments);
            }
        };
    }

प्रयोज्य:

var obj = {};
overload(obj, 'function_name', function(){ /* what we will do if no args passed? */});
overload(obj, 'function_name', function(first){ /* what we will do if 1 arg passed? */});
overload(obj, 'function_name', function(first, second){ /* what we will do if 2 args passed? */});
overload(obj, 'function_name', function(first,second,third){ /* what we will do if 3 args passed? */});
//... etc :)

4

जावास्क्रिप्ट में आप केवल एक बार फ़ंक्शन को लागू कर सकते हैं और मापदंडों के बिना फ़ंक्शन को लागू कर सकते हैं myFunc() आप फिर यह देखने के लिए जांचें कि क्या विकल्प 'अपरिभाषित' है

function myFunc(options){
 if(typeof options != 'undefined'){
  //code
 }
}

3

मैंने यहाँ वर्णित इस समस्या का एक सुरुचिपूर्ण समाधान विकसित करने की कोशिश की । और आप यहां डेमो पा सकते हैं । उपयोग इस तरह दिखता है:

var out = def({
    'int': function(a) {
        alert('Here is int '+a);
    },

    'float': function(a) {
        alert('Here is float '+a);
    },

    'string': function(a) {
        alert('Here is string '+a);
    },

    'int,string': function(a, b) {
        alert('Here is an int '+a+' and a string '+b);
    },
    'default': function(obj) {
        alert('Here is some other value '+ obj);
    }

});

out('ten');
out(1);
out(2, 'robot');
out(2.5);
out(true);

इसे प्राप्त करने के लिए इस्तेमाल की जाने वाली विधियाँ:

var def = function(functions, parent) {
 return function() {
    var types = [];
    var args = [];
    eachArg(arguments, function(i, elem) {
        args.push(elem);
        types.push(whatis(elem));
    });
    if(functions.hasOwnProperty(types.join())) {
        return functions[types.join()].apply(parent, args);
    } else {
        if (typeof functions === 'function')
            return functions.apply(parent, args);
        if (functions.hasOwnProperty('default'))
            return functions['default'].apply(parent, args);        
    }
  };
};

var eachArg = function(args, fn) {
 var i = 0;
 while (args.hasOwnProperty(i)) {
    if(fn !== undefined)
        fn(i, args[i]);
    i++;
 }
 return i-1;
};

var whatis = function(val) {

 if(val === undefined)
    return 'undefined';
 if(val === null)
    return 'null';

 var type = typeof val;

 if(type === 'object') {
    if(val.hasOwnProperty('length') && val.hasOwnProperty('push'))
        return 'array';
    if(val.hasOwnProperty('getDate') && val.hasOwnProperty('toLocaleTimeString'))
        return 'date';
    if(val.hasOwnProperty('toExponential'))
        type = 'number';
    if(val.hasOwnProperty('substring') && val.hasOwnProperty('length'))
        return 'string';
 }

 if(type === 'number') {
    if(val.toString().indexOf('.') > 0)
        return 'float';
    else
        return 'int';
 }

 return type;
};

1
आदानों को संभालने के लिए एक फ़ंक्शन, बहुत चालाक।
ट्रैविस जे

3

https://github.com/jrf0110/leFunc

var getItems = leFunc({
  "string": function(id){
    // Do something
  },
  "string,object": function(id, options){
    // Do something else
  },
  "string,object,function": function(id, options, callback){
    // Do something different
    callback();
  },
  "object,string,function": function(options, message, callback){
    // Do something ca-raaaaazzzy
    callback();
  }
});

getItems("123abc"); // Calls the first function - "string"
getItems("123abc", {poop: true}); // Calls the second function - "string,object"
getItems("123abc", {butt: true}, function(){}); // Calls the third function - "string,object,function"
getItems({butt: true}, "What what?" function(){}); // Calls the fourth function - "object,string,function"

3

जेएस में ओवरलोडिंग के साथ कोई समस्या नहीं, कार्यभार ओवरलोडिंग करते समय एक साफ कोड कैसे बनाए रखें?

आप दो चीज़ों के आधार पर एक साफ़ कोड का उपयोग कर सकते हैं:

  1. तर्कों की संख्या (फ़ंक्शन को कॉल करते समय)।
  2. तर्कों के प्रकार (फ़ंक्शन को कॉल करते समय)

      function myFunc(){
          return window['myFunc_'+arguments.length+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments);
       }
    
        /** one argument & this argument is string */
      function myFunc_1_string(){
    
      }
       //------------
       /** one argument & this argument is object */
      function myFunc_1_object(){
    
      }
      //----------
      /** two arguments & those arguments are both string */
      function myFunc_2_string_string(){
    
      }
       //--------
      /** Three arguments & those arguments are : id(number),name(string), callback(function) */
      function myFunc_3_number_string_function(){
                let args=arguments;
                  new Person(args[0],args[1]).onReady(args[3]);
      }
    
       //--- And so on ....   

2

इसकी जांच करें:

http://www.codeproject.com/Articles/688869/Overloading-JavaScript-Functions

मूल रूप से आपकी कक्षा में, आप अपने कार्यों को संख्या देते हैं जिन्हें आप अतिभारित करना चाहते हैं और फिर एक फ़ंक्शन कॉल के साथ आप फ़ंक्शन को ओवरलोडिंग, तेज और आसान जोड़ते हैं।


2

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

function optionsObjectTest(x, y, opts) {
    opts = opts || {}; // default to an empty options object

    var stringValue = opts.stringValue || "string default value";
    var boolValue = !!opts.boolValue; // coerces value to boolean with a double negation pattern
    var numericValue = opts.numericValue === undefined ? 123 : opts.numericValue;

    return "{x:" + x + ", y:" + y + ", stringValue:'" + stringValue + "', boolValue:" + boolValue + ", numericValue:" + numericValue + "}";

}

यहाँ कैसे विकल्प वस्तु का उपयोग करने पर एक उदाहरण है


2

इसके लिए आपको एक फ़ंक्शन बनाना होगा जो फ़ंक्शन को ऑब्जेक्ट में जोड़ता है, फिर यह आपके द्वारा फ़ंक्शन को भेजे जाने वाले तर्कों की मात्रा के आधार पर निष्पादित करेगा:

<script > 
//Main function to add the methods
function addMethod(object, name, fn) {
  var old = object[name];
  object[name] = function(){
    if (fn.length == arguments.length)
      return fn.apply(this, arguments)
    else if (typeof old == 'function')
      return old.apply(this, arguments);
  };
}


  var ninjas = {
   values: ["Dean Edwards", "Sam Stephenson", "Alex Russell"]
};

//Here we declare the first function with no arguments passed
  addMethod(ninjas, "find", function(){
    return this.values;
});

//Second function with one argument
  addMethod(ninjas, "find", function(name){
    var ret = [];
    for (var i = 0; i < this.values.length; i++)
      if (this.values[i].indexOf(name) == 0)
        ret.push(this.values[i]);
    return ret;
  });

//Third function with two arguments
  addMethod(ninjas, "find", function(first, last){
    var ret = [];
    for (var i = 0; i < this.values.length; i++)
      if (this.values[i] == (first + " " + last))
        ret.push(this.values[i]);
    return ret;
  });


//Now you can do:
ninjas.find();
ninjas.find("Sam");
ninjas.find("Dean", "Edwards")
</script>

0

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

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

doSomething.withArgSet1 = function(arg0, arg1) {
    var obj = new doSomething();
    // do something the first way
    return obj;
};

doSomething.withArgSet2 = function(arg2, arg3) {
    var obj = new doSomething();
    // do something the second way
    return obj;
};

0

आप जो हासिल करने की कोशिश कर रहे हैं, वह फ़ंक्शन के स्थानीय तर्कों चर का उपयोग करके किया जाता है ।

function foo() {
    if (arguments.length === 0) {
        //do something
    }
    if (arguments.length === 1) {
        //do something else
    }
}

foo(); //do something
foo('one'); //do something else

आप इस बारे में बेहतर व्याख्या पा सकते हैं कि यह यहाँ कैसे काम करता है


और टक्कर का पता लगाने के बारे में क्या? यह पैरामीटर रहित फ़ंक्शंस का उपयोग करने या अस्तित्व की जांच करने का एक अच्छा तरीका है, लेकिन जब यह ओवरलोडिंग की बात आती है तो वास्तव में सबसे अच्छा अभ्यास नहीं है।
ट्रैविस जे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.