जावास्क्रिप्ट में फ़ंक्शन ओवरलोडिंग - सर्वोत्तम अभ्यास


782

जावास्क्रिप्ट में ओवरलोडिंग करने के लिए सबसे अच्छा तरीका क्या है?

मुझे पता है कि अन्य भाषाओं की तरह जावास्क्रिप्ट में कार्यों को अधिभार देना संभव नहीं है। अगर मुझे दो उपयोगों के साथ एक फ़ंक्शन की आवश्यकता है foo(x)और foo(x,y,z)जो सबसे अच्छा / पसंदीदा तरीका है:

  1. पहली बार में विभिन्न नामों का उपयोग करना
  2. जैसे वैकल्पिक तर्कों का उपयोग करना y = y || 'default'
  3. तर्कों की संख्या का उपयोग करना
  4. तर्कों की जाँच करना
  5. या कैसे?

14
शायद यह पूछना उपयोगी होगा कि आपको लगता है कि आपको शुरू करने के लिए फ़ंक्शन ओवरलोडिंग की आवश्यकता क्यों है। मुझे लगता है कि यह हमें एक वास्तविक समाधान के करीब ले जाएगा।
ब्रेटन

1
यह बंद है, लेकिन मैं निम्न कार्य करता हूं: this.selectBy = {उदाहरण: selectByInstance, // फ़ंक्शन टेक्स्ट: selectByText, // फ़ंक्शन मान: selectByValue // फ़ंक्शन};
कैदी जीरो

मेरा जवाब दिखाता है कि रनिंग फंक्शन ओवरलोडिंग कैसे किया जाता है, इसमें गति दंड है और मैं इसे जावास्क्रिप्ट के विनिर्देश के आसपास लाने के लिए ऐसा करने की सलाह नहीं दूंगा। फ़ंक्शन ओवरलोडिंग वास्तव में एक संकलन समय का काम है, मैं केवल अकादमिक उद्देश्यों के लिए उत्तर प्रदान करता हूं और इसे अपने विवेक पर छोड़ता हूं कि क्या इसे कोड में नियोजित करना है या नहीं।
क्लेडॉन एलेनी

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

जवाबों:


602

मापदंडों के साथ फ़ंक्शन ओवरलोडिंग करने का सबसे अच्छा तरीका तर्क लंबाई या प्रकारों की जांच करना नहीं है; प्रकारों की जाँच करने से आपका कोड धीमा हो जाएगा और आपको ऐरेज़, नल, ऑब्जेक्ट्स आदि का मज़ा मिलेगा।

अधिकांश डेवलपर्स क्या करते हैं, किसी वस्तु पर उनके तरीकों के अंतिम तर्क के रूप में व्यवहार करते हैं। यह वस्तु कुछ भी धारण कर सकती है।

function foo(a, b, opts) {
  // ...
  if (opts['test']) { } //if test param exists, do something.. 
}


foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});

फिर आप इसे वैसे भी संभाल सकते हैं, जैसा आप अपनी विधि में चाहते हैं। [स्विच, यदि-आदि, आदि]


43
क्या आप फू () का एक नमूना कार्यान्वयन प्रदान कर सकते हैं जो दर्शाता है कि इन "ऑप्स" मापदंडों का उपयोग कैसे किया जाता है / संदर्भित?
मो हावर्ड

24
मो // यह ऐसा हो सकता है; if(opts['test']) //if test param exists, do something.. if(opts['bar']) //if bar param exists, do something
डेकार्ड

80
यह कार्य ओवरलोडिंग नहीं है। फ़ंक्शन ओवरलोडिंग में एक ही नाम के साथ दो अलग-अलग कार्य होते हैं, लेकिन अलग-अलग पैरामीटर। आप जो वर्णन कर रहे हैं वह अंत में एक वस्तु तर्क के साथ केवल एक कार्य है।
d512

66
@ user1334007 यह कार्य करना असंभव है जैसे आप इसे जावा / .NET में करेंगे। हाँ, यह "बिल्कुल" ओवरलोडिंग नहीं है, लेकिन यह काम करता है।
epascarello

18
मुझे आश्चर्य है कि किसी ने भी यह पहले से नहीं पूछा: जाँच arguments.lengthकी सिफारिश क्यों नहीं की गई है? इसके अलावा, मैं यहां पहले भी पढ़ चुका हूं और पढ़ता हूं कि ज्यादातर डेवलपर्स क्या करते हैं ... , लेकिन मुझे यकीन है कि यह एकमात्र ऐसा स्थान है जिसे मैंने देखा है। यह विधि 'ओवरलोड' होने की संश्लिष्ट शर्करा को भी बिगाड़ देती है!
c24w

169

मैं अक्सर ऐसा करता हूं:

सी#:

public string CatStrings(string p1)                  {return p1;}
public string CatStrings(string p1, int p2)          {return p1+p2.ToString();}
public string CatStrings(string p1, int p2, bool p3) {return p1+p2.ToString()+p3.ToString();}

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

जावास्क्रिप्ट समतुल्य:

function CatStrings(p1, p2, p3)
{
  var s = p1;
  if(typeof p2 !== "undefined") {s += p2;}
  if(typeof p3 !== "undefined") {s += p3;}
  return s;
};

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

यह विशेष उदाहरण वास्तव में C # की तुलना में जावास्क्रिप्ट में अधिक सुरुचिपूर्ण है। जो पैरामीटर्स निर्दिष्ट नहीं हैं, वे जावास्क्रिप्ट में 'अपरिभाषित' हैं, जो कि एक स्टेटमेंट में गलत का मूल्यांकन करता है। हालाँकि, फंक्शन डेफिनिशन से यह जानकारी नहीं मिलती है कि पी 2 और पी 3 वैकल्पिक हैं। यदि आपको बहुत अधिक लोडिंग की आवश्यकता है, तो jQuery ने एक ऑब्जेक्ट को पैरामीटर के रूप में उपयोग करने का निर्णय लिया है, उदाहरण के लिए, jQuery.ajax (विकल्प)। मैं उनसे सहमत हूं कि यह ओवरलोडिंग के लिए सबसे शक्तिशाली और स्पष्ट रूप से दस्तावेजी दृष्टिकोण है, लेकिन मुझे शायद ही कभी एक या दो से अधिक वैकल्पिक वैकल्पिक मापदंडों की आवश्यकता होती है।

EDIT: IAN के सुझाव के अनुसार IF परीक्षण बदल दिया गया


16
पैरामीटर जो निर्दिष्ट नहीं हैं, undefinedवे जेएस में हैं, नहीं null। एक सर्वोत्तम अभ्यास के रूप में, आपको कभी भी कुछ भी निर्धारित नहीं करना चाहिए undefined, इसलिए जब तक आप अपना परीक्षण नहीं बदलते हैं, तब तक यह समस्या नहीं होनी चाहिए p2 === undefined
तामजिन ब्लेक

3
यदि आप falseअंतिम तर्क के रूप में पास होते हैं , तो यह "false"अंत तक if(p3)नहीं होगा , क्योंकि शाखा नहीं होगी।
ड्रीमलैक्स

5
बस एक त्वरित नोट, आपका typeof p2 === "undefined"शायद आपके उदाहरण के उदाहरण में आप जो अपेक्षा कर रहे हैं, उसका उल्टा है, मुझे लगता typeof p2 !== "undefined"है कि आपका क्या इरादा है। इसके अलावा, मेरा सुझाव है कि आप इसे स्ट्रिंग, संख्या और बूलियन के रूप में p2 === "number"; p3 === "boolean"
समझ

8
मुझे ऐसा करना पसंद है: p3 = p3 || 'डिफ़ॉल्ट मान';
डोरियन

3
का अर्थ क्या है ===और !==? सिर्फ उपयोग ==और क्यों नहीं !=?
रिकार्डो क्रूज़

76

जावास्क्रिप्ट में कोई वास्तविक कार्य नहीं है क्योंकि यह किसी भी प्रकार के किसी भी पैरामीटर को पारित करने की अनुमति देता है। आपको फ़ंक्शन के अंदर यह जांचना होगा कि कितने तर्क पारित किए गए हैं और वे किस प्रकार के हैं।


1
जॉन रेसिग (jQuery के) ने एक बार यह कोशिश की थी, लेकिन यह प्रयास पूरी तरह से अकादमिक था और इससे कोई वास्तविक लाभ नहीं मिला।
scunliffe

14
जॉन रेजिग
Terrance

@ चेतावनी: मुझे रेसिग का तरीका भी पसंद है। यह एक सम्मोहन की तरह काम करता है। मुझे केवल उपयोग के मामलों को मान्य करने के लिए एक परीक्षण बनाने का तरीका खोजने की आवश्यकता है।
क्रिसविल्लेन्यूवा

"यह फ़ंक्शन दुनिया को नहीं बदलेगा, लेकिन यह संक्षिप्त, संक्षिप्त है, और एक अस्पष्ट जावास्क्रिप्ट सुविधा का उपयोग करता है - इसलिए यह मेरी पुस्तक में जीतता है।" :-)
फ्रेरिच राबे

66

इसका सही उत्तर है JAVASCRIPT में कोई विज्ञापन नहीं है।

फ़ंक्शन के अंदर चेकिंग / स्विचिंग ओवरलोइंग नहीं है।

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

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

https://en.wikipedia.org/wiki/Function_overloading

सभी सुझाए गए कार्यान्वयन महान हैं, लेकिन सच कहा जाए, तो जावास्क्रिप्ट के लिए कोई मूल कार्यान्वयन नहीं है।


4
अंत में एक सामान्य जवाब! यहां JAVASCRIPT में कोई सामान नहीं है।
रज़वान टुडोरिका

4
ओपी ने फर्जी ओवरलोडिंग का रास्ता पूछा ।
अंतूर गेम्स

जैसा कि मैंने पहले कहा था, हम यहां लोगों को शिक्षित कर रहे हैं, हम उन्हें बिना सत्यापित किए जवाब नहीं देते कि वे जो पूछ रहे हैं वह सही है।
मार्को

27

ऐसे दो तरीके हैं जिनसे आप बेहतर तरीके से संपर्क कर सकते हैं:

  1. यदि आप बहुत अधिक लचीलापन छोड़ना चाहते हैं तो एक शब्दकोश (साहचर्य सरणी) पास करें

  2. ऑब्जेक्ट को तर्क के रूप में लें और लचीलापन जोड़ने के लिए प्रोटोटाइप आधारित वंशानुक्रम का उपयोग करें।


1
यह मेरा प्रारंभिक विचार था, हालाँकि, यदि आप जो फ़ंक्शन बना रहे हैं, उसका उपयोग लाइब्रेरी में या दूसरों द्वारा किया जाना है, तो मानों को स्पष्ट रूप से
समझाना

19

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

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

संपादित करें (2018) : चूंकि यह 2011 में लिखा गया था, इसलिए प्रत्यक्ष विधि कॉल की गति बहुत बढ़ गई है, जबकि ओवरलोड तरीकों की गति नहीं हुई है।

यह एक दृष्टिकोण नहीं है जिसे मैं सुझाऊंगा, लेकिन यह सोचने के लिए एक सार्थक विचार अभ्यास है कि आप इस प्रकार की समस्याओं को कैसे हल कर सकते हैं।


यहाँ विभिन्न दृष्टिकोणों का एक बेंचमार्क है - https://jsperf.com/function-overloading । यह दिखाता है कि Google Chrome के V8 में 16.0 (बीटा) के रूप में फ़ंक्शन ओवरलोडिंग (खाते में प्रकार लेना) लगभग 13 गुना धीमा हो सकता है ।

एक वस्तु (यानी {x: 0, y: 0}) को पारित करने के साथ , एक भी उचित तरीके से नामकरण करते समय, सी दृष्टिकोण ले सकता है। उदाहरण के लिए, Vector.AddVector (वेक्टर), Vector.AddIntegers (x, y, z, ...) और Vector.AddArray (पूर्णांकर)। आप C पुस्तकालयों को देख सकते हैं, जैसे कि नामकरण प्रेरणा के लिए OpenGL।

संपादित करें : मैंने किसी ऑब्जेक्ट को पास करने के लिए 'param' in argऔर दोनों का उपयोग करके ऑब्जेक्ट के लिए एक बेंचमार्क जोड़ा है arg.hasOwnProperty('param'), और फ़ंक्शन ओवरलोडिंग किसी ऑब्जेक्ट को पास करने और गुणों की जांच करने की तुलना में बहुत तेज है (इस बेंचमार्क में कम से कम)।

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

मेरा उदाहरण आयत कार्यान्वयन से आया है - इसलिए आयाम और बिंदु का उल्लेख है। शायद आयत और प्रोटोटाइप में एक GetRectangle()विधि जोड़ सकता है , और फिर फ़ंक्शन ओवरलोडिंग समस्या हल हो जाती है। और आदिमयों के बारे में क्या? खैर, हमारे पास तर्क की लंबाई है, जो अब एक वैध परीक्षण है क्योंकि वस्तुओं में एक विधि है।DimensionPointGetRectangle()

function Dimension() {}
function Point() {}

var Util = {};

Util.Redirect = function (args, func) {
  'use strict';
  var REDIRECT_ARGUMENT_COUNT = 2;

  if(arguments.length - REDIRECT_ARGUMENT_COUNT !== args.length) {
    return null;
  }

  for(var i = REDIRECT_ARGUMENT_COUNT; i < arguments.length; ++i) {
    var argsIndex = i-REDIRECT_ARGUMENT_COUNT;
    var currentArgument = args[argsIndex];
    var currentType = arguments[i];
    if(typeof(currentType) === 'object') {
      currentType = currentType.constructor;
    }
    if(typeof(currentType) === 'number') {
      currentType = 'number';
    }
    if(typeof(currentType) === 'string' && currentType === '') {
      currentType = 'string';
    }
    if(typeof(currentType) === 'function') {
      if(!(currentArgument instanceof currentType)) {
        return null;
      }
    } else {
      if(typeof(currentArgument) !== currentType) {
        return null;
      }
    } 
  }
  return [func.apply(this, args)];
}

function FuncPoint(point) {}
function FuncDimension(dimension) {}
function FuncDimensionPoint(dimension, point) {}
function FuncXYWidthHeight(x, y, width, height) { }

function Func() {
  Util.Redirect(arguments, FuncPoint, Point);
  Util.Redirect(arguments, FuncDimension, Dimension);
  Util.Redirect(arguments, FuncDimensionPoint, Dimension, Point);
  Util.Redirect(arguments, FuncXYWidthHeight, 0, 0, 0, 0);
}

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

16

सबसे अच्छा तरीका वास्तव में फ़ंक्शन और तर्कों पर निर्भर करता है। आपका प्रत्येक विकल्प विभिन्न स्थितियों में एक अच्छा विचार है। जब तक उनमें से कोई एक काम करता है मैं आम तौर पर निम्नलिखित क्रम में इनकी कोशिश करता हूं:

  1. Y = y जैसे वैकल्पिक तर्कों का उपयोग करना || 'चूक'। यह सुविधाजनक है यदि आप इसे कर सकते हैं, लेकिन यह हमेशा व्यावहारिक रूप से काम नहीं कर सकता है, उदाहरण के लिए जब 0 / null / अपरिभाषित एक वैध तर्क होगा।

  2. तर्कों की संख्या का उपयोग करना। अंतिम विकल्प के समान लेकिन जब # 1 काम नहीं करता है तो काम कर सकता है।

  3. तर्कों के प्रकार की जाँच। यह कुछ मामलों में काम कर सकता है जहां तर्कों की संख्या समान है। यदि आप मज़बूती से प्रकार निर्धारित नहीं कर सकते हैं, तो आपको विभिन्न नामों का उपयोग करने की आवश्यकता हो सकती है।

  4. पहली बार में विभिन्न नामों का उपयोग करना। आपको यह करने की आवश्यकता हो सकती है यदि अन्य विकल्प काम नहीं करेंगे, व्यावहारिक नहीं हैं, या अन्य संबंधित कार्यों के साथ संगतता के लिए।


14

अगर मुझे दो उपयोगों फू (x) और foo (x, y, z) के साथ एक फ़ंक्शन की आवश्यकता है जो सबसे अच्छा / पसंदीदा तरीका है?

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

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

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

function foo(x)
{
} 

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

fooNew(x,y,z)
{
}

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

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

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

( अधिक जानकारी )

पुनश्च: उपरोक्त लिंक मेरे व्यक्तिगत ब्लॉग पर जाता है जिसमें अतिरिक्त विवरण हैं।


9

मैं सर्वश्रेष्ठ अभ्यास के बारे में निश्चित नहीं हूं, लेकिन यहां बताया गया है कि मैं यह कैसे करता हूं:

/*
 * Object Constructor
 */
var foo = function(x) {
    this.x = x;
};

/*
 * Object Protoype
 */
foo.prototype = {
    /*
     * f is the name that is going to be used to call the various overloaded versions
     */
    f: function() {

        /*
         * Save 'this' in order to use it inside the overloaded functions
         * because there 'this' has a different meaning.
         */   
        var that = this;  

        /* 
         * Define three overloaded functions
         */
        var f1 = function(arg1) {
            console.log("f1 called with " + arg1);
            return arg1 + that.x;
        }

        var f2 = function(arg1, arg2) {
             console.log("f2 called with " + arg1 + " and " + arg2);
             return arg1 + arg2 + that.x;
        }

        var f3 = function(arg1) {
             console.log("f3 called with [" + arg1[0] + ", " + arg1[1] + "]");
             return arg1[0] + arg1[1];
        }

        /*
         * Use the arguments array-like object to decide which function to execute when calling f(...)
         */
        if (arguments.length === 1 && !Array.isArray(arguments[0])) {
            return f1(arguments[0]);
        } else if (arguments.length === 2) {
            return f2(arguments[0], arguments[1]);
        } else if (arguments.length === 1 && Array.isArray(arguments[0])) {
            return f3(arguments[0]);
        }
    } 
}

/* 
 * Instantiate an object
 */
var obj = new foo("z");

/*
 * Call the overloaded functions using f(...)
 */
console.log(obj.f("x"));         // executes f1, returns "xz"
console.log(obj.f("x", "y"));    // executes f2, returns "xyz"
console.log(obj.f(["x", "y"]));  // executes f3, returns "xy"

2
@Luis: मैंने कुछ उम्मीद से उपयोगी टिप्पणियां जोड़ी हैं।
चेसवेब

6

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

TEST = {};

TEST.multiFn = function(){
    // function map for our overloads
    var fnMap = {};

    fnMap[0] = function(){
        console.log("nothing here");
        return this;    //    support chaining
    }

    fnMap[1] = function(arg1){
        //    CODE here...
        console.log("1 arg: "+arg1);
        return this;
    };

    fnMap[2] = function(arg1, arg2){
        //    CODE here...
        console.log("2 args: "+arg1+", "+arg2);
        return this;
    };

    fnMap[3] = function(arg1,arg2,arg3){
        //    CODE here...
        console.log("3 args: "+arg1+", "+arg2+", "+arg3);
        return this;
    };

    console.log("multiFn is now initialized");

    //    redefine the function using the fnMap in the closure
    this.multiFn = function(){
        fnMap[arguments.length].apply(this, arguments);
        return this;
    };

    //    call the function since this code will only run once
    this.multiFn.apply(this, arguments);

    return this;    
};

झसे आज़माओ।

TEST.multiFn("0")
    .multiFn()
    .multiFn("0","1","2");

5

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

    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 + "}";

}

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


4

जावास्क्रिप्ट में ओवरलोडिंग को कार्य करने का कोई तरीका नहीं है। इसलिए, मैं typeof()फर्जी ओवरलोडिंग के लिए कई फ़ंक्शन के बजाय विधि द्वारा निम्नलिखित की तरह अनुशंसा करता हूं ।

function multiTypeFunc(param)
{
    if(typeof param == 'string') {
        alert("I got a string type parameter!!");
     }else if(typeof param == 'number') {
        alert("I got a number type parameter!!");
     }else if(typeof param == 'boolean') {
        alert("I got a boolean type parameter!!");
     }else if(typeof param == 'object') {
        alert("I got a object type parameter!!");
     }else{
        alert("error : the parameter is undefined or null!!");
     }
}

सौभाग्य!


24
भगवान के लिए! एक स्विच स्टेटमेंट का उपयोग करें!
jedmao

8
इसके अलावा, यदि आप एक स्विच का उपयोग न करने का आग्रह करते हैं, तो आपको केवल एक बार टाइपोफ को कॉल करना चाहिए। var type = typeof param; if (type === 'string') ...
वाल्टर स्टबोज़

+1 करने के लिए "===" टिप्पणी करें। स्विच स्टेटमेंट का अन्य लाभ यदि (... == ...) है तो यह सुरक्षित है।
नाथन कूपर

4

परिचय

अब तक इतने जवाबों को पढ़कर किसी को भी सिरदर्द हो जाता था। किसी को भी इस अवधारणा को जानने की कोशिश करने के लिए निम्न शर्त जानने की आवश्यकता होगी ।

Function overloading Definition, Function Length property,Function argument property

Function overloadingइसके सबसे सरल रूप में इसका मतलब है कि एक फ़ंक्शन विभिन्न तर्कों के आधार पर विभिन्न कार्य करता है जो इसे पारित किया जा रहा है। विशेष रूप से TASK1, TASK2 और TASK3 को नीचे हाइलाइट किया argumentsगया है और एक ही फ़ंक्शन में दिए जाने की संख्या के आधार पर प्रदर्शन किया जा रहा है fooYo

// if we have a function defined below
function fooYo(){
     // do something here
}
// on invoking fooYo with different number of arguments it should be capable to do different things

fooYo();  // does TASK1
fooYo('sagar'); // does TASK2
fooYo('sagar','munjal'); // does TAKS3

नोट - JS फ़ंक्शन ओवरलोडिंग की इनबिल्ट क्षमता प्रदान नहीं करता है।

विकल्प

जॉन ई रेसिग (जेएस के निर्माता) ने एक विकल्प बताया है जो फ़ंक्शन लोडिंग को लागू करने की क्षमता प्राप्त करने के लिए उपरोक्त आवश्यक शर्तें का उपयोग करता है।

नीचे दिए गए कोड का उपयोग करके if-elseया switchकथन द्वारा एक सीधा लेकिन अनुभवहीन दृष्टिकोण का उपयोग किया जाता है।

  • argument-lengthसंपत्ति का मूल्यांकन करता है।
  • विभिन्न मूल्यों के परिणामस्वरूप अलग-अलग कार्य होते हैं।

var ninja = {
  whatever: function() {
       switch (arguments.length) {
         case 0:
           /* do something */
           break;
         case 1:
           /* do something else */
           break;
         case 2:
           /* do yet something else */
           break;
       //and so on ...
    } 
  }
}

एक और तकनीक बहुत अधिक स्वच्छ और गतिशील है। इस तकनीक का मुख्य आकर्षण addMethodसामान्य कार्य है।

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

  • addMethodफ़ंक्शन के नीचे तीन परम ऑब्जेक्ट नाम object, फ़ंक्शन नाम nameऔर उस फ़ंक्शन को स्वीकार करता है जिसे हम आमंत्रित करना चाहते हैं fn

  • अंदर की addMethodपरिभाषा var oldपिछले संदर्भ को functionबंद करने की मदद से संग्रहीत करती है - एक सुरक्षात्मक बुलबुला।

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);
  };
};

  • कोड प्रवाह को समझने के लिए डीबगर का उपयोग करें।
  • नीचे दिए गए addMethodतीन फ़ंक्शंस जो कि ninja.whatever(x)तर्कों की संख्या का उपयोग करके आह्वान किए गए हैं, xजो कि कुछ भी हो सकते हैं, या तो रिक्त हो सकते हैं या एक या एक से अधिक फ़ंक्शन के उपयोग करते समय परिभाषित किए गए विभिन्न कार्यों को आमंत्रित करते हैं addMethod

var ninja = {};
debugger;


addMethod(ninja,'whatever',function(){ console.log("I am the one with ZERO arguments supplied") });
addMethod(ninja,'whatever',function(a){ console.log("I am the one with ONE arguments supplied") });
addMethod(ninja,'whatever',function(a,b){ console.log("I am the one with TWO arguments supplied") });


ninja.whatever();
ninja.whatever(1,2);
ninja.whatever(3);


4

यह दृष्टिकोण करने के लिए एक और तरीका विशेष चर का उपयोग करके है: तर्क , यह एक कार्यान्वयन है:

function sum() {
    var x = 0;
    for (var i = 0; i < arguments.length; ++i) {
        x += arguments[i];
    }
    return x;
}

इसलिए आप इस कोड को संशोधित कर सकते हैं:

function sum(){
    var s = 0;
    if (typeof arguments[0] !== "undefined") s += arguments[0];
.
.
.
    return s;
}

3

इसकी जांच करें। यह बहुत ठंडा है। http://ejohn.org/blog/javascript-method-overloading/ ट्रिक जावास्क्रिप्ट आपको इस तरह से कॉल करने की अनुमति देने के लिए:

var users = new Users();
users.find(); // Finds all
users.find("John"); // Finds users by name
users.find("John", "Resig"); // Finds users by first and last name

हाय जैदर, मेरे जवाब की जांच करें, इसमें वास्तविक जावास्क्रिप्ट विधि के लिए कोड है जो ओवरलोडिंग है। मैं बात कर रहा हूं Func(new Point())और Func(new Rectangle())विभिन्न कार्यों को अंजाम दूंगा। लेकिन मुझे कहना होगा कि यह एक गंदी हैक है, क्योंकि विधि अधिभार वास्तव में एक संकलन समय कार्य है जो समय नहीं चलाता है।
क्लेडॉन एलेनी

3

जावास्क्रिप्ट में फ़ंक्शन ओवरलोडिंग:

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

जावास्क्रिप्ट नहीं करता अंतर्निहित समारोह से अधिक भार। हालाँकि, इस व्यवहार का कई तरीकों से अनुकरण किया जा सकता है। यहाँ एक सुविधाजनक सरल है:

function sayHi(a, b) {
  console.log('hi there ' + a);
  if (b) { console.log('and ' + b) } // if the parameter is present, execute the block
}

sayHi('Frank', 'Willem');

स्थितियों में आप नहीं जानते कि जहां कितने तर्क आप आप उपयोग कर सकते हो रही होगी बाकी ऑपरेटर जो तीन बिंदुओं है ...। यह शेष तर्कों को एक सरणी में बदल देगा। हालांकि ब्राउज़र कॉम्पैटिबिलिटी से सावधान रहें। यहाँ एक उदाहरण है:

function foo (a, ...b) {
  console.log(b);
}

foo(1,2,3,4);
foo(1,2);


2

जैसा कि इस पोस्ट में पहले से ही बहुत सारे अलग-अलग समाधान हैं मुझे लगा कि मैं एक और पोस्ट करता हूं।

function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

function overload() {
   var functions = arguments;
   var nroffunctionsarguments = [arguments.length];
    for (var i = 0; i < arguments.length; i++) {
        nroffunctionsarguments[i] = arguments[i].length;
    }
    var unique = nroffunctionsarguments.filter(onlyUnique);
    if (unique.length === arguments.length) {
        return function () {
            var indexoffunction = nroffunctionsarguments.indexOf(arguments.length);
            return functions[indexoffunction].apply(this, arguments);
        }
    }
    else throw new TypeError("There are multiple functions with the same number of parameters");

}

इसे नीचे दिखाए अनुसार उपयोग किया जा सकता है:

var createVector = overload(
        function (length) {
            return { x: length / 1.414, y: length / 1.414 };
        },
        function (a, b) {
            return { x: a, y: b };
        },
        function (a, b,c) {
            return { x: a, y: b, z:c};
        }
    );
console.log(createVector(3, 4));
console.log(createVector(3, 4,5));
console.log(createVector(7.07));

यह समाधान सही नहीं है, लेकिन मैं केवल प्रदर्शित करने के लिए यह कैसे किया जा सकता है चाहता हूँ।


2

आप जॉन रेसिग से 'addMethod' का उपयोग कर सकते हैं। इस पद्धति के साथ आप तर्कों की गणना के आधार पर "ओवरलोड" तरीके कर सकते हैं।

// addMethod - By John Resig (MIT Licensed)
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 );
    };
}

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

// addMethod - By Stavros Ioannidis
function addMethod(obj, name, fn) {
  obj[name] = obj[name] || function() {
    // get the cached method with arguments.length arguments
    var method = obj[name].cache[arguments.length];

    // if method exists call it 
    if ( !! method)
      return method.apply(this, arguments);
    else throw new Error("Wrong number of arguments");
  };

  // initialize obj[name].cache
  obj[name].cache = obj[name].cache || {};

  // Check if a method with the same number of arguments exists  
  if ( !! obj[name].cache[fn.length])
    throw new Error("Cannot define multiple '" + name +
      "' methods with the same number of arguments!");

  // cache the method with fn.length arguments
  obj[name].cache[fn.length] = function() {
    return fn.apply(this, arguments);
  };
}

2

फॉरवर्डिंग पैटर्न => जेएस ओवरलोडिंग पर सबसे अच्छा अभ्यास

एक और फ़ंक्शन के लिए अग्रेषित करें, जिसे 3 और 4 अंक से बनाया गया है:

  1. तर्कों की संख्या का उपयोग करना
  2. तर्कों की जाँच करना
window['foo_'+arguments.length+'_'+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments)

आपके मामले पर आवेदन:

 function foo(){
          return window['foo_'+arguments.length+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments);

  }
   //------Assuming that `x` , `y` and `z` are String when calling `foo` . 

  /**-- for :  foo(x)*/
  function foo_1_string(){
  }
  /**-- for : foo(x,y,z) ---*/
  function foo_3_string_string_string(){

  }

अन्य जटिल नमूना:

      function foo(){
          return window['foo_'+arguments.length+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments);
       }

        /** one argument & this argument is string */
      function foo_1_string(){

      }
       //------------
       /** one argument & this argument is object */
      function foo_1_object(){

      }
      //----------
      /** two arguments & those arguments are both string */
      function foo_2_string_string(){

      }
       //--------
      /** Three arguments & those arguments are : id(number),name(string), callback(function) */
      function foo_3_number_string_function(){
                let args=arguments;
                  new Person(args[0],args[1]).onReady(args[3]);
      }

       //--- And so on ....   

2

जे एस के 100 लाइनों में गतिशील बहुरूपता के माध्यम से समारोह ओवरलोडिंग

  • वेनिलाजेएस, कोई बाहरी निर्भरता नहीं
  • पूर्ण ब्राउज़र समर्थन - Array.prototyp.slice , Object.prototyp.toString
  • 1114 बाइट्स uglify'd / 744 बाइट्स जी-ज़िप्ड

इस कोड का एक बड़ा शरीर जिसमें शामिल है से है isFn, isArrआदि प्रकार की जाँच के काम करता है। नीचे दिए गए वनीलाजेएस संस्करण को सभी बाहरी निर्भरता को दूर करने के लिए फिर से काम किया गया है, हालांकि आपको .add()कॉल में उपयोग के लिए स्वयं के प्रकार के कार्यों की जांच करनी होगी ।

नोट: यह एक स्व-निष्पादित फ़ंक्शन है (इसलिए हमारे पास एक क्लोजर / क्लोज्ड स्कोप हो सकता है), इसलिए इसके window.overloadबजाय असाइनमेंट function overload() {...}

window.overload = function () {
    "use strict"

    var a_fnOverloads = [],
        _Object_prototype_toString = Object.prototype.toString
    ;

    function isFn(f) {
        return (_Object_prototype_toString.call(f) === '[object Function]');
    } //# isFn

    function isObj(o) {
        return !!(o && o === Object(o));
    } //# isObj

    function isArr(a) {
        return (_Object_prototype_toString.call(a) === '[object Array]');
    } //# isArr

    function mkArr(a) {
        return Array.prototype.slice.call(a);
    } //# mkArr

    function fnCall(fn, vContext, vArguments) {
        //# <ES5 Support for array-like objects
        //#     See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Browser_compatibility
        vArguments = (isArr(vArguments) ? vArguments : mkArr(vArguments));

        if (isFn(fn)) {
            return fn.apply(vContext || this, vArguments);
        }
    } //# fnCall

    //# 
    function registerAlias(fnOverload, fn, sAlias) {
        //# 
        if (sAlias && !fnOverload[sAlias]) {
            fnOverload[sAlias] = fn;
        }
    } //# registerAlias

    //# 
    function overload(vOptions) {
        var oData = (isFn(vOptions) ?
                { default: vOptions } :
                (isObj(vOptions) ?
                    vOptions :
                    {
                        default: function (/*arguments*/) {
                            throw "Overload not found for arguments: [" + mkArr(arguments) + "]";
                        }
                    }
                )
            ),
            fnOverload = function (/*arguments*/) {
                var oEntry, i, j,
                    a = arguments,
                    oArgumentTests = oData[a.length] || []
                ;

                //# Traverse the oArgumentTests for the number of passed a(rguments), defaulting the oEntry at the beginning of each loop
                for (i = 0; i < oArgumentTests.length; i++) {
                    oEntry = oArgumentTests[i];

                    //# Traverse the passed a(rguments), if a .test for the current oArgumentTests fails, reset oEntry and fall from the a(rgument)s loop
                    for (j = 0; j < a.length; j++) {
                        if (!oArgumentTests[i].tests[j](a[j])) {
                            oEntry = undefined;
                            break;
                        }
                    }

                    //# If all of the a(rgument)s passed the .tests we found our oEntry, so break from the oArgumentTests loop
                    if (oEntry) {
                        break;
                    }
                }

                //# If we found our oEntry above, .fn.call its .fn
                if (oEntry) {
                    oEntry.calls++;
                    return fnCall(oEntry.fn, this, a);
                }
                //# Else we were unable to find a matching oArgumentTests oEntry, so .fn.call our .default
                else {
                    return fnCall(oData.default, this, a);
                }
            } //# fnOverload
        ;

        //# 
        fnOverload.add = function (fn, a_vArgumentTests, sAlias) {
            var i,
                bValid = isFn(fn),
                iLen = (isArr(a_vArgumentTests) ? a_vArgumentTests.length : 0)
            ;

            //# 
            if (bValid) {
                //# Traverse the a_vArgumentTests, processinge each to ensure they are functions (or references to )
                for (i = 0; i < iLen; i++) {
                    if (!isFn(a_vArgumentTests[i])) {
                        bValid = _false;
                    }
                }
            }

            //# If the a_vArgumentTests are bValid, set the info into oData under the a_vArgumentTests's iLen
            if (bValid) {
                oData[iLen] = oData[iLen] || [];
                oData[iLen].push({
                    fn: fn,
                    tests: a_vArgumentTests,
                    calls: 0
                });

                //# 
                registerAlias(fnOverload, fn, sAlias);

                return fnOverload;
            }
            //# Else one of the passed arguments was not bValid, so throw the error
            else {
                throw "poly.overload: All tests must be functions or strings referencing `is.*`.";
            }
        }; //# overload*.add

        //# 
        fnOverload.list = function (iArgumentCount) {
            return (arguments.length > 0 ? oData[iArgumentCount] || [] : oData);
        }; //# overload*.list

        //# 
        a_fnOverloads.push(fnOverload);
        registerAlias(fnOverload, oData.default, "default");

        return fnOverload;
    } //# overload

    //# 
    overload.is = function (fnTarget) {
        return (a_fnOverloads.indexOf(fnTarget) > -1);
    } //# overload.is

    return overload;
}();

उपयोग:

फोन करने वाले को रिटर्न के लिए एक चर असाइन करके उनके अतिभारित कार्यों को परिभाषित करता है overload()। चेनिंग के लिए धन्यवाद, अतिरिक्त अधिभार को श्रृंखला में परिभाषित किया जा सकता है:

var myOverloadedFn = overload(function(){ console.log("default", arguments) })
    .add(function(){ console.log("noArgs", arguments) }, [], "noArgs")
    .add(function(){ console.log("str", arguments) }, [function(s){ return typeof s === 'string' }], "str")
;

overload()हस्ताक्षर की पहचान नहीं होने पर कॉल करने के लिए "डिफ़ॉल्ट" फ़ंक्शन को परिभाषित करने के लिए एकल वैकल्पिक तर्क । .add()निम्न तर्क हैं:

  1. fn: functionअधिभार को परिभाषित करना;
  2. a_vArgumentTests: Arrayके functionपरीक्षण को परिभाषित रों पर चलने के लिए arguments। यदि कोई तर्क मान्य है, तो प्रत्येक functionएक तर्क को स्वीकार करता है और trueआपके आधार को लौटाता है;
  3. sAlias(वैकल्पिक): stringओवरलोड फ़ंक्शन को सीधे एक्सेस करने के लिए उपनाम को परिभाषित करना ( fn), उदाहरण myOverloadedFn.noArgs()के लिए तर्कों के गतिशील बहुरूपता परीक्षणों से बचते हुए, सीधे उस फ़ंक्शन को कॉल करेगा।

यह कार्यान्वयन वास्तव में पारंपरिक फ़ंक्शन को ओवरलोड से अधिक के लिए अनुमति देता है क्योंकि अभ्यास में दूसरा a_vArgumentTestsतर्क .add()कस्टम प्रकारों को परिभाषित करता है। इसलिए, आप न केवल प्रकार के आधार पर, बल्कि श्रेणियों, मूल्यों या मूल्यों के संग्रह पर भी तर्क दे सकते हैं!

यदि आप कोड की 145 पंक्तियों के माध्यम से overload()देखते हैं , तो आप देखेंगे कि प्रत्येक हस्ताक्षर argumentsको उसमें पारित संख्या के आधार पर वर्गीकृत किया गया है। ऐसा इसलिए किया जाता है ताकि हम उन परीक्षणों की संख्या को सीमित कर रहे हैं जिन्हें हम चला रहे हैं। मैं एक कॉल काउंट पर भी नज़र रखता हूँ। कुछ अतिरिक्त कोड के साथ, ओवरलोड कार्यों के सरणियों को फिर से क्रमबद्ध किया जा सकता है ताकि अधिक सामान्यतः कार्यों को पहले परीक्षण किया जा सके, फिर से प्रदर्शन बढ़ाने के कुछ उपायों को जोड़ा जा सके।

अब, कुछ कैविएट हैं ... जैसा कि जावास्क्रिप्ट शिथिल टाइप किया जाता है, आपको अपने साथ सावधानी बरतनी होगी vArgumentTestsक्योंकि एक के integerरूप में मान्य किया जा सकता है float, आदि।

JSCompress.com संस्करण (1114 बाइट्स, 744 बाइट्स जी-ज़िप्ड):

window.overload=function(){'use strict';function b(n){return'[object Function]'===m.call(n)}function c(n){return!!(n&&n===Object(n))}function d(n){return'[object Array]'===m.call(n)}function e(n){return Array.prototype.slice.call(n)}function g(n,p,q){if(q=d(q)?q:e(q),b(n))return n.apply(p||this,q)}function h(n,p,q){q&&!n[q]&&(n[q]=p)}function k(n){var p=b(n)?{default:n}:c(n)?n:{default:function(){throw'Overload not found for arguments: ['+e(arguments)+']'}},q=function(){var r,s,t,u=arguments,v=p[u.length]||[];for(s=0;s<v.length;s++){for(r=v[s],t=0;t<u.length;t++)if(!v[s].tests[t](u[t])){r=void 0;break}if(r)break}return r?(r.calls++,g(r.fn,this,u)):g(p.default,this,u)};return q.add=function(r,s,t){var u,v=b(r),w=d(s)?s.length:0;if(v)for(u=0;u<w;u++)b(s[u])||(v=_false);if(v)return p[w]=p[w]||[],p[w].push({fn:r,tests:s,calls:0}),h(q,r,t),q;throw'poly.overload: All tests must be functions or strings referencing `is.*`.'},q.list=function(r){return 0<arguments.length?p[r]||[]:p},l.push(q),h(q,p.default,'default'),q}var l=[],m=Object.prototype.toString;return k.is=function(n){return-1<l.indexOf(n)},k}();

2

अब आप पॉलीफ़िल्स के बिना ECMAScript 2018 में फंक्शन ओवरलोडिंग कर सकते हैं, var लंबाई / प्रकार आदि की जाँच कर सकते हैं, बस फैल सिंटैक्स का उपयोग कर सकते हैं

function foo(var1, var2, opts){
  // set default values for parameters
  const defaultOpts = {
    a: [1,2,3],
    b: true,
    c: 0.3289,
    d: "str",
  }
  // merge default and passed-in parameters
  // defaultOpts must go first!
  const mergedOpts = {...defaultOpts, ...opts};

  // you can now refer to parameters like b as mergedOpts.b,
  // or just assign mergedOpts.b to b
  console.log(mergedOpts.a);
  console.log(mergedOpts.b);
  console.log(mergedOpts.c);  
  console.log(mergedOpts.d);
}
// the parameters you passed in override the default ones
// all JS types are supported: primitives, objects, arrays, functions, etc.
let var1, var2="random var";
foo(var1, var2, {a: [1,2], d: "differentString"});

// parameter values inside foo:
//a: [1,2]
//b: true
//c: 0.3289
//d: "differentString"

फैला हुआ वाक्यविन्यास क्या है?

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

नोट: वस्तु शाब्दिक रूप से सिंटैक्स का प्रसार एज और IE में काम नहीं करता है और यह एक प्रायोगिक विशेषता है। ब्राउज़र संगतता देखें


2

फ़ंक्शन ओवरलोडिंग के लिए ऐसा कुछ किया जा सकता है।

function addCSS(el, prop, val) {
  return {
    2: function() {
      // when two arguments are set
      // now prop is an oject
      for (var i in prop) {
          el.style[i] = prop[i];
      }
    },
    3: function() {
      // when three arguments are set
      el.style[prop] = val;
    }
    }[arguments.length]();
}
// usage
var el = document.getElementById("demo");
addCSS(el, "color", "blue");
addCSS(el, {
    "backgroundColor": "black",
  "padding": "10px"
});

स्रोत


1

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

var foo;

// original 'foo' definition
foo = function(a) {
  console.log("a: " + a);
}

// define 'foo' to accept two arguments
foo = (function() {
  // store a reference to the previous definition of 'foo'
  var old = foo;

  // use inline function so that you can refer to it internally
  return function newFoo(a,b) {

    // check that the arguments.length == the number of arguments 
    // defined for 'newFoo'
    if (arguments.length == newFoo.length) {
      console.log("a: " + a);
      console.log("b: " + b);

    // else if 'old' is a function, apply it to the arguments
    } else if (({}).toString.call(old) === '[object Function]') {
      old.apply(null, arguments);
    }
  }
})();

foo(1);
> a: 1
foo(1,2);
> a: 1
> b: 2
foo(1,2,3)
> a: 1

संक्षेप में, IIFE का उपयोग एक स्थानीय गुंजाइश बनाता है, जिससे हमें oldफ़ंक्शन की प्रारंभिक परिभाषा के संदर्भ में स्टोर करने के लिए निजी चर को परिभाषित करने की अनुमति मिलती है foo। यह फ़ंक्शन तब एक इनलाइन फ़ंक्शन देता है जो newFooदोनों दो तर्कों की सामग्री को लॉग करता है यदि यह बिल्कुल दो तर्कों को पारित किया जाता है aऔर यदि फ़ंक्शन को bकॉल oldकरता है arguments.length !== 2। इस पैटर्न को कई अलग-अलग कार्यात्मक सुरक्षा के साथ एक चर को समाप्त करने के लिए किसी भी संख्या में दोहराया जा सकता है।


1

मैं ओवरलोड-जैसे दृष्टिकोण का एक उपयोगी उदाहरण साझा करना चाहूंगा।

function Clear(control)
{
  var o = typeof control !== "undefined" ? control : document.body;
  var children = o.childNodes;
  while (o.childNodes.length > 0)
    o.removeChild(o.firstChild);
}

उपयोग: साफ़ (); // सभी दस्तावेज़ को साफ़ करता है

साफ़ (myDiv); // क्लीयर पैनल myDiv द्वारा संदर्भित


1

जावास्क्रिप्ट लावारिस भाषा है, और मुझे केवल यही लगता है कि एक विधि / कार्य को ओवरले की संख्या के संबंध में समझ में आता है। इसलिए, मैं जाँचने की सलाह दूंगा कि क्या पैरामीटर परिभाषित किया गया है:

myFunction = function(a, b, c) {
     if (b === undefined && c === undefined ){
          // do x...
     }
     else {
          // do y...
     }
};

1
बस यह ध्यान रखना चाहते हैं कि अप्रकाशित का अर्थ "कोई प्रकार" नहीं है।
हम्दीकोगुज

1

जुलाई 2017 तक, निम्नलिखित सामान्य तकनीक रही है। ध्यान दें कि हम फ़ंक्शन के भीतर टाइप चेकिंग भी कर सकते हैं।

function f(...rest){   // rest is an array
   console.log(rest.length);
   for (v of rest) if (typeof(v)=="number")console.log(v);
}
f(1,2,3);  // 3 1 2 3

1

आपके उपयोग के मामले के लिए, यह है कि मैं इससे कैसे निपटूंगा ES6(क्योंकि यह पहले से ही 2017 के अंत में है):

const foo = (x, y, z) => {
  if (y && z) {
    // Do your foo(x, y, z); functionality
    return output;
  }
  // Do your foo(x); functionality
  return output;
}

आप स्पष्ट रूप से किसी भी राशि के मापदंडों के साथ काम करने के लिए इसे अनुकूलित कर सकते हैं और बस तदनुसार अपने सशर्त विवरण बदल सकते हैं।


1

जेएस में कोई वास्तविक ओवरलोडिंग नहीं है, वैसे भी हम अभी भी कई तरीकों से ओवरलोडिंग की विधि का अनुकरण कर सकते हैं:

विधि # 1: ऑब्जेक्ट का उपयोग करें

function test(x,options){
  if("a" in options)doSomething();
  else if("b" in options)doSomethingElse();
}
test("ok",{a:1});
test("ok",{b:"string"});

विधि # 2: आराम (प्रसार) मापदंडों का उपयोग करें

function test(x,...p){
 if(p[2])console.log("3 params passed"); //or if(typeof p[2]=="string")
else if (p[1])console.log("2 params passed");
else console.log("1 param passed");
}

विधि # 3: अपरिभाषित का उपयोग करें

function test(x, y, z){
 if(typeof(z)=="undefined")doSomething();
}

विधि # 4: प्रकार की जाँच

function test(x){
 if(typeof(x)=="string")console.log("a string passed")
 else ...
}

1

जबकि डिफ़ॉल्ट पैरामीटर ओवरलोडिंग नहीं है, यह उन कुछ समस्याओं को हल कर सकता है जो डेवलपर्स इस क्षेत्र में सामना करते हैं। इनपुट सख्ती से आदेश द्वारा तय किया गया है, आप फिर से आदेश नहीं दे सकते हैं जैसा कि आप शास्त्रीय ओवरलोडिंग में चाहते हैं:

function transformer(
    firstNumber = 1,
    secondNumber = new Date().getFullYear(),
    transform = function multiply(firstNumber, secondNumber) {
        return firstNumber * secondNumber;
    }
) {
    return transform(firstNumber, secondNumber);
}

console.info(transformer());
console.info(transformer(8));
console.info(transformer(2, 6));
console.info(transformer(undefined, 65));

function add(firstNumber, secondNumber) {
    return firstNumber + secondNumber;
}
console.info(transformer(undefined, undefined, add));
console.info(transformer(3, undefined, add));

वर्ष 2020 के लिए परिणाम:

2020
16160
12
65
2021
2023

अधिक जानकारी: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters


0

पहला विकल्प वास्तव में ध्यान देने योग्य है क्योंकि यह वह चीज है जो मैं काफी जटिल कोड सेटअप में आया हूं। तो, मेरा जवाब है

  1. पहली बार में विभिन्न नामों का उपयोग करना

थोड़ा लेकिन आवश्यक संकेत के साथ, नाम कंप्यूटर के लिए अलग दिखना चाहिए, लेकिन आपके लिए नहीं। नाम अतिभारित कार्य जैसे: func1, func1, func2।


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