कार्य करने के लिए तर्कों की जावास्क्रिप्ट चर संख्या


531

क्या जावास्क्रिप्ट में एक फ़ंक्शन के लिए "असीमित" संस्करण की अनुमति देने का एक तरीका है?

उदाहरण:

load(var1, var2, var3, var4, var5, etc...)
load(var1)



1
@ ल्यूक नहीं, यह नहीं है। यह प्रश्न पूछता है कि किसी फ़ंक्शन को किसी सरणी में तर्कों के साथ मनमानी संख्या के साथ कैसे कॉल किया जाए। यह पूछता है कि इस तरह के कॉल को कैसे संभालना है।
स्क्रूफी

1
आसान खोज के लिए, इस तरह के फ़ंक्शन को 'वैरेडिक फ़ंक्शन' कहा जाता है।
gschenk

जवाबों:


814

ज़रूर, बस argumentsवस्तु का उपयोग करें ।

function foo() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}

1
Tnx। यह एक वेबव्यू में Android देशी कोड से जावास्क्रिप्ट के लिए स्ट्रिंग्स पार्स करने के लिए बहुत अच्छा है।
जोहान होक्समा

4
इस समाधान ने मेरे लिए सबसे अच्छा काम किया। धन्यवाद। यहाँ तर्क तर्कों पर अधिक जानकारी ।
User 2

26
argumentsएक विशेष "ऐरे-लाइक" ऑब्जेक्ट है, जिसका अर्थ है कि इसकी लंबाई है, लेकिन कोई अन्य फ़ंक्शन नहीं है। अधिक जानकारी के लिए developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… देखें , और यह उत्तर: stackoverflow.com/a/13145228/1766230
ल्यूक

4
दिलचस्प बात यह है कि जावास्क्रिप्ट में ऐरे तरीकों को इस तरह से परिभाषित किया गया है कि वे किसी भी वस्तु पर काम करते हैं, जिसके पास एक lengthसंपत्ति है। इसमें argumentsवस्तु शामिल है । यह जानते हुए भी, और यह विधि 'सरणी' की एक प्रतिconcat लौटाती है जिस पर इसे कहा जाता है, हम argumentsवस्तु को एक वास्तविक सरणी में आसानी से बदल सकते हैं जैसे कि var args = [].concat.call(arguments):। कुछ लोग Array.prototype.concat.callइसके बजाय उपयोग करना पसंद करते हैं , लेकिन मुझे पसंद है [], वे छोटे और मीठे हैं!
स्टिज डे विट

2
@ यासिरजन का उपयोग[...arguments].join()
विलियन डी। एंड्रेड

179

(अधिकांश) हाल के ब्राउज़रों में, आप इस वाक्यविन्यास के साथ चर संख्याओं को स्वीकार कर सकते हैं:

function my_log(...args) {
     // args is an Array
     console.log(args);
     // You can pass this array as parameters to another function
     console.log(...args);
}

यहाँ एक छोटा सा उदाहरण दिया गया है:

function foo(x, ...args) {
  console.log(x, args, ...args, arguments);
}

foo('a', 'b', 'c', z='d')

=>

a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
    0: "a"
    1: "b"
    2: "c"
    3: "d"
    length: 4

प्रलेखन और अधिक उदाहरण यहां: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters


27
FYI करें इसे "बाकी पैरामीटर सिंटैक्स" कहा जाता है: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
tanguy_k

4
+1 यह सुरुचिपूर्ण और साफ समाधान है। विशेष रूप से दूसरे फ़ंक्शन कॉल में मापदंडों की लंबी सूची से गुजरने के लिए उपयुक्त है, और संभव है कि वे चर पैरामीटर मनमाने स्थिति पर हों।
por:५५ बजे por:

3
ध्यान रखें कि developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… के अनुसार यह IE पर समर्थित नहीं है।
रूई गेवरिल

2
यहाँ ब्राउज़र समर्थन दिखाने वाली एक तालिका है - caniuse.com/#feat=rest-parameters
Brian Burns

1
इतना अच्छा जवाब!
आशीष

113

एक अन्य विकल्प एक संदर्भ वस्तु में अपने तर्कों को पारित करना है।

function load(context)
{
    // do whatever with context.name, context.address, etc
}

और इसे इस तरह से उपयोग करें

load({name:'Ken',address:'secret',unused:true})

इसका यह फायदा है कि आप जितने चाहें उतने नामित तर्क जोड़ सकते हैं, और फ़ंक्शन उन्हें उपयोग कर सकता है (या नहीं) जैसा कि वह फिट देखता है।


4
यह बेहतर होगा क्योंकि यह युग्मन को तर्क क्रम में हटा देता है। ढीले-ढाले युग्मित इंटरफेस अच्छे मानक अभ्यास हैं ...
जोनास शूबर्ट एर्लडसन 20

9
यकीन है, कि कुछ मामलों में बेहतर है। लेकिन मान लें कि व्यक्तिगत तर्क वास्तव में एक-दूसरे से संबंधित नहीं हैं, या सभी को समान अर्थ के लिए माना जाता है (जैसे सरणी तत्व)। फिर ओपी का तरीका सबसे अच्छा है।
rvighne

1
यह भी अच्छा है क्योंकि यदि आप चाहें, तो आप contextकोड के साथ तर्क का निर्माण कर सकते हैं और इसे उपयोग करने से पहले इसे चारों ओर से पारित कर सकते हैं ।
नैट सीके

46

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

function load(context) {

    var defaults = {
        parameter1: defaultValue1,
        parameter2: defaultValue2,
        ...
    };

    var context = extend(defaults, context);

    // do stuff
}

इस तरह, यदि आपके पास कई पैरामीटर हैं, लेकिन जरूरी नहीं कि उन्हें फ़ंक्शन के लिए प्रत्येक कॉल के साथ सेट करने की आवश्यकता है, तो आप बस गैर-चूक को निर्दिष्ट कर सकते हैं। विस्तार विधि के लिए, आप jQuery की विस्तार विधि ( $.extend()) का उपयोग कर सकते हैं , अपना स्वयं का शिल्प कर सकते हैं या निम्नलिखित का उपयोग कर सकते हैं:

function extend() {
    for (var i = 1; i < arguments.length; i++)
        for (var key in arguments[i])
            if (arguments[i].hasOwnProperty(key))
                arguments[0][key] = arguments[i][key];
    return arguments[0];
}

यह संदर्भ ऑब्जेक्ट को डिफॉल्ट्स के साथ मर्ज कर देगा और डिफॉल्ट्स के साथ आपकी ऑब्जेक्ट में किसी अपरिभाषित मान को भर देगा।


3
+1। अच्छी चाल। प्रत्येक पैरामीटर को परिभाषित, डिफ़ॉल्ट या अन्यथा करने के लिए बहुत सारे बॉयलर प्लेट बचाता है।
नील

1
अंडरस्कोर की _.defaults() विधि निर्दिष्ट और डिफ़ॉल्ट तर्कों को मर्ज करने का एक बहुत अच्छा विकल्प है।
mbeasley

18

हां, बस इस तरह:

function load()
{
  var var0 = arguments[0];
  var var1 = arguments[1];
}

load(1,2);

18

रेस्ट पैरामीटर सिंटैक्स का उपयोग करना बेहतर होता है क्योंकि रामस्ट ने बताया।

function (a, b, ...args) {}

मैं सिर्फ कुछ अच्छी संपत्ति जोड़ना चाहता हूँ ... तर्क तर्क

  1. यह एक सरणी है, और तर्क जैसी कोई वस्तु नहीं है। यह आपको सीधे मानचित्र जैसे कार्यों को लागू करने की अनुमति देता है।
  2. इसमें सभी पैरामीटर शामिल नहीं हैं, लेकिन इसमें से केवल एक ही पास हुआ है। इस मामले में एग फ़ंक्शन (ए, बी, ... आर्ग्स) में तर्क 3 से तर्कों में शामिल हैं

15

जैसा कि पहले ही उल्लेख किया गया है, आप argumentsफ़ंक्शन मापदंडों के एक चर संख्या को पुनः प्राप्त करने के लिए ऑब्जेक्ट का उपयोग कर सकते हैं ।

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

log() {
    let args = Array.prototype.slice.call(arguments);
    args = ['MyObjectName', this.id_].concat(args);
    console.log.apply(console, args);
}

तर्कों को सरणी में बदलने के लिए अच्छा समाधान। यह आज मेरे लिए मददगार था।
Dmytro Medvid

8

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

function load(context) {
   var parameter1 = context.parameter1 || defaultValue1,
       parameter2 = context.parameter2 || defaultValue2;

   // do stuff
}

यह लगभग समान मात्रा का कोड है (शायद थोड़ा अधिक), लेकिन रनटाइम लागत का एक अंश होना चाहिए।


सहमत, हालांकि नुकसान मूल्य या डिफ़ॉल्ट के प्रकार पर निर्भर करता है। अन्यथा, (parameter1=context.parameter1)===undefined && (parameter1=defaultValue1)या कम कोड वॉल्यूम के लिए एक छोटा सहायक फ़ंक्शन जैसे: function def(providedValue, default) {return providedValue !== undefined ? providedValue : defaultValue;} var parameter1 = def(context.parameter1, defaultValue1)वैकल्पिक पैटर्न प्रदान करें। हालाँकि, मेरी बात अब भी कायम है: हर फंक्शन के इनवोकेशन के लिए अतिरिक्त ऑब्जेक्ट बनाना और डिफ़ॉल्ट वैल्यू के एक जोड़े को सेट करने के लिए महंगे लूप चलाना ओवरहेड की एक पागल राशि है।
mcurland

7

जबकि @roufamatic ने तर्कों का उपयोग दिखाया था और @Ken ने उपयोग के लिए किसी ऑब्जेक्ट का एक शानदार उदाहरण दिखाया था, मुझे लगता है कि इस उदाहरण में जो चल रहा है उसे न तो सही मायने में संबोधित किया जा सकता है और न भविष्य के पाठकों को भ्रमित कर सकता है और न ही खराब व्यवहार के लिए प्रेरित कर सकता है क्योंकि यह स्पष्ट रूप से एक फ़ंक्शन नहीं बताता है। / विधि का तर्क / मापदंडों की एक चर राशि लेने का इरादा है।

function varyArg () {
    return arguments[0] + arguments[1];
}

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

आइए स्पष्ट रूप से बताएं कि एक ही फ़ंक्शन में परिवर्तनीय पैरामीटर हैं:

function varyArg (var_args) {
    return arguments[0] + arguments[1];
}

ऑब्जेक्ट पैरामीटर VS var_args

ऐसा समय हो सकता है जब किसी ऑब्जेक्ट की आवश्यकता होती है क्योंकि यह डेटा मैप का एकमात्र स्वीकृत और माना जाने वाला सबसे अच्छा अभ्यास तरीका है। साहचर्य सरणियों पर डूब जाते हैं और हतोत्साहित किया जाता है।

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

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

function varyArg (args_obj) {
    return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});

कौन सा चुनना है?

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

तर्क का उपयोग

function sumOfAll (var_args) {
    return arguments.reduce(function(a, b) {
        return a + b;
    }, 0);
}
sumOfAll(1,2,3); // returns 6

वस्तु का उपयोग

function myObjArgs(args_obj) {
    // MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
    if (typeof args_obj !== "object") {
        return "Arguments passed must be in object form!";
    }

    return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old

किसी ऑब्जेक्ट के बजाय एक सरणी तक पहुंच ("... args" बाकी पैरामीटर)

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

Array.prototype.map.call(arguments, function (val, idx, arr) {});

इससे बचने के लिए बाकी पैरामीटर का उपयोग करें:

function varyArgArr (...var_args) {
    return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5

5

argumentsजब फ़ंक्शन अंदर हो तो उस ऑब्जेक्ट का उपयोग करें जिसमें पास किए गए सभी तर्कों तक पहुंच हो।


3

ज्ञात रहे कि केन के सुझाए गए गुणों के साथ ऑब्जेक्ट पास करना, प्रत्येक कॉल पर अस्थायी ऑब्जेक्ट को आवंटित करने और जारी करने की लागत को जोड़ता है। मूल्य या संदर्भ द्वारा सामान्य तर्क पारित करना आमतौर पर सबसे अधिक कुशल होगा। कई अनुप्रयोगों के लिए हालांकि प्रदर्शन महत्वपूर्ण नहीं है, लेकिन कुछ के लिए यह हो सकता है।

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