क्या जावास्क्रिप्ट फ़ंक्शन में चर संख्या में तर्क भेजना संभव है?


170

क्या किसी सरणी से, जावास्क्रिप्ट फ़ंक्शन के चर संख्या को भेजना संभव है?

var arr = ['a','b','c']

var func = function()
{
    // debug 
    alert(arguments.length);
    //
    for(arg in arguments)
        alert(arg);
}

func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(arr); // prints 1, then 'Array'

मैंने हाल ही में बहुत सारे पायथन को लिखा है और यह एक अद्भुत पैटर्न है जो वेरगैस को स्वीकार करने और उन्हें भेजने में सक्षम है। जैसे

def func(*args):
   print len(args)
   for i in args:
       print i

func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(*arr) // prints 4 which is what I want, then 'a','b','c','d'

क्या यह संभव है कि जावास्क्रिप्ट में तर्क सरणी के रूप में एक सरणी भेजा जाए ?


4
ध्यान दें कि वस्तु के for - inसाथ लूप का उपयोग करने के लिए इसका अच्छा विचार नहीं है arguments- lengthसंपत्ति पर लूप के लिए एक 'सामान्य' इसके बजाय इस्तेमाल किया जाना चाहिए
यी जियांग

2
यह कभी कोई समस्या नहीं है, क्या आप इस बात पर विचार कर सकते हैं कि ऐसा क्यों है? तर्कों का उपयोग लगभग हमेशा काफी छोटा होता है, जो कि एग्रेसिव [0..length-1] संस्करण का उपयोग करने के लिए एक नगण्य प्रदर्शन में सुधार होता है।
अग्नि क्रो


1
मुझे लगता है कि तर्क एक वास्तविक सरणी नहीं है, लेकिन एक विशेष वस्तु है, इसलिए जेएस कार्यान्वयन के आधार पर "इन" सिंटैक्स काम नहीं कर सकता है।
O'Rooney

जवाबों:


207

अद्यतन : ES6 के बाद से, आप बस फ़ंक्शन को कॉल करते समय फैल सिंटैक्स का उपयोग कर सकते हैं :

func(...arr);

चूंकि ES6 भी अगर आप अपने तर्कों को एक सरणी के रूप में मानते हैं, तो आप उदाहरण के लिए, पैरामीटर सूची में प्रसार सिंटैक्स का उपयोग कर सकते हैं:

function func(...args) {
  args.forEach(arg => console.log(arg))
}

const values = ['a', 'b', 'c']
func(...values)
func(1, 2, 3)

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

function func(first, second, ...theRest) {
  //...
}

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

var test = function (one, two, three) {}; 
test.length == 3;

लेकिन वैसे भी आप एक मनमानी संख्या पास कर सकते हैं ...

स्प्रेड सिंटैक्स छोटा और "मीठा" होता है apply और यदि आपको thisफ़ंक्शन कॉल में मान सेट करने की आवश्यकता नहीं है , तो यह जाने का तरीका है।

यहाँ एक है लागू उदाहरण है, जो यह करने के लिए पूर्व जिस तरह से किया गया था:

var arr = ['a','b','c'];

function func() {
  console.log(this); // 'test'
  console.log(arguments.length); // 3

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

};

func.apply('test', arr);

आजकल मैं केवल उपयोग करने की अनुशंसा applyकेवल यदि आप एक सरणी से युक्तियों के स्वेच्छाचारी संख्या में उत्तीर्ण होना और सेट thisमूल्य। पहले मान के रूप applyमें thisमान का उपयोग किया जाता है, जिसका उपयोग फ़ंक्शन इनवोकेशन पर किया जाएगा, यदि हम nullगैर-सख्त कोड में उपयोग करते हैं , तो thisकीवर्ड ग्लोबल ऑब्जेक्ट (विंडो) के अंदर संदर्भित करेगाfunc , सख्त मोड में, स्पष्ट रूप से 'उपयोग सख्त' का उपयोग करेगा। 'या ES मॉड्यूल में, nullका उपयोग किया जाएगा।

यह भी ध्यान दें कि argumentsवस्तु वास्तव में एक सरणी नहीं है, आप इसे इसके द्वारा परिवर्तित कर सकते हैं:

var argsArray = Array.prototype.slice.call(arguments);

और ES6 में:

const argsArray = [...arguments] // or Array.from(arguments)

लेकिन आप शायद ही कभी argumentsवस्तु का उपयोग करते हैं आजकल प्रसार सिंटैक्स के लिए धन्यवाद।


1
धन्यवाद, लागू करें चाल करता है, इस मामले में कॉल काम नहीं करता है। क्या वह गलती से लिखा गया था?
अग्नि कौवा

यदि फ़ंक्शन वास्तव में एक वर्ग का सदस्य है तो आप इसे कैसे करते हैं? क्या यह सही है? TheObject.member.apply (TheObject, तर्क);
बैक्सीसिमो

4
Array.prototype.slice.call(arguments);V8 जैसे ब्राउज़र जेएस अनुकूलन को रोकता है। यहाँ विवरण
धीरज भास्कर

2
1. जाहिर है, प्रसार ऑपरेटर केarguments पक्ष में पदावनत किए जाने की योजना है । मेरे पास इसके लिए कोई स्रोत नहीं है, लेकिन मैंने इसे कहीं सुना है। 2. एमडीएन बताता है कि ऑब्जेक्ट पर उपयोग वी 8 जैसे इंजन में अनुकूलन को रोकता है। वे "तिरस्कृत ऐरे निर्माता" , या का उपयोग करने का सुझाव देते हैं । क्या आप ES2015 के लिए अपना जवाब अपडेट करना चाहेंगे? sliceargumentsArray.from(arguments)[...arguments]
ब्रैडेन बेस्ट

NB: मैं आगे गया और अपना जवाब लिखा ।
ब्रैडेन बेस्ट

75

आप वास्तव में किसी भी जावास्क्रिप्ट फ़ंक्शन के लिए जितने चाहें उतने मान पास कर सकते हैं। स्पष्ट रूप से नामित पैरामीटर पहले कुछ मान प्राप्त करेंगे, लेकिन सभी पैरामीटर तर्क सरणी में संग्रहीत किए जाएंगे।

"अनपैक्ड" फ़ॉर्म में तर्कों को पास करने के लिए, आप आवेदन का उपयोग कर सकते हैं, जैसे (सीएफ कार्यात्मक जावास्क्रिप्ट ):

var otherFunc = function() {
   alert(arguments.length); // Outputs: 10
}

var myFunc = function() {
  alert(arguments.length); // Outputs: 10
  otherFunc.apply(this, arguments);
}
myFunc(1,2,3,4,5,6,7,8,9,10);

23

सूचक और प्रसार ऑपरेटरों ES6, जावास्क्रिप्ट की योजना बनाई अगले संस्करण का हिस्सा हैं। अभी तक केवल फ़ायरफ़ॉक्स ही उनका समर्थन करता है। यह कोड FF16 + में काम करता है:

var arr = ['quick', 'brown', 'lazy'];

var sprintf = function(str, ...args)
{
    for (arg of args) {
        str = str.replace(/%s/, arg);
    }
    return str;
}

sprintf.apply(null, ['The %s %s fox jumps over the %s dog.', ...arr]);
sprintf('The %s %s fox jumps over the %s dog.', 'slow', 'red', 'sleeping');

प्रसार के लिए अजीब सिंटैक्स पर ध्यान दें। का सामान्य वाक्य विन्यासsprintf('The %s %s fox jumps over the %s dog.', ...arr); है अभी तक समर्थित नहीं । आप यहां ES6 संगतता तालिका पा सकते हैं ।

for...ofएक और ES6 जोड़ के उपयोग पर भी ध्यान दें । for...inसरणियों के लिए उपयोग करना एक बुरा विचार है


प्रसार के लिए सामान्य वाक्यविन्यास अब फ़ायरफ़ॉक्स और क्रोम
उपयोगकर्ता

8

applyसमारोह दो तर्क लेता है; ऑब्जेक्ट thisको सरणी के साथ दर्शाया गया है, और तर्कों को बाँधा जाएगा।

some_func = function (a, b) { return b }
some_func.apply(obj, ["arguments", "are", "here"])
// "are"

8

ES2015 के रूप में दो विधियाँ हैं।

argumentsवस्तु

यह ऑब्जेक्ट फ़ंक्शंस में बनाया गया है, और यह एक फ़ंक्शन के तर्क को उचित रूप से संदर्भित करता है। यह तकनीकी रूप से एक सरणी नहीं है, हालाँकि, विशिष्ट प्रकार के ऑपरेशन इस पर काम नहीं करेंगे। सुझाई गई विधि का उपयोग करना है Array.fromया उससे एक सरणी बनाने के लिए प्रसार ऑपरेटर का उपयोग करना है।

मैंने अन्य उत्तर का उपयोग करते हुए उल्लेख किया है slice। ऐसा मत करो। यह अनुकूलन को रोकता है (स्रोत: एमडीएन )।

Array.from(arguments)
[...arguments]

हालाँकि, मैं तर्क दूंगा कि argumentsयह समस्याग्रस्त है क्योंकि यह छिपाता है कि एक फ़ंक्शन इनपुट के रूप में क्या स्वीकार करता है। एक argumentsफ़ंक्शन आमतौर पर इस तरह लिखा जाता है:

function mean(){
    let args = [...arguments];
    return args.reduce((a,b)=>a+b) / args.length;
}

कभी-कभी, फ़ंक्शन हेडर को सी-लाइक फ़ैशन में तर्कों को दस्तावेज़ करने के लिए निम्न प्रकार लिखा जाता है:

function mean(/* ... */){ ... }

लेकिन ऐसा कम ही होता है।

उदाहरण के लिए, समस्याग्रस्त क्यों है, C को लें। C, K & R C. K & R C के रूप में जानी जाने वाली भाषा की एक प्राचीन पूर्व-ANSI बोली के साथ पीछे की ओर संगत है, फ़ंक्शन प्रोटोटाइप को खाली तर्क सूची रखने की अनुमति देता है।

int myFunction();
/* This function accepts unspecified parameters */

ANSI C एक खाली तर्क-सूची निर्दिष्ट करने के लिए varargs( ...), और के लिए एक सुविधा प्रदान करता है void

int myFunction(void);
/* This function accepts no parameters */

कई लोग अनजाने में एक unspecifiedतर्क सूची ( int myfunction();) के साथ फ़ंक्शन की घोषणा करते हैं , जब वे फ़ंक्शन से शून्य तर्क लेने की अपेक्षा करते हैं। यह तकनीकी रूप से एक बग है क्योंकि फ़ंक्शन तर्कों को स्वीकार करेगा । उनमें से कोई भी संख्या।

varargsसी में एक उचित कार्य रूप लेता है:

int myFunction(int nargs, ...);

और जावास्क्रिप्ट वास्तव में इस के समान कुछ है।

प्रसार संचालक / रेस्ट पैरामीटर्स

मैंने आपको पहले ही फैले हुए ऑपरेटर को दिखाया है, वास्तव में।

...name

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

function mean(...args){
    return args.reduce((a,b)=>a+b) / args.length;
}

या लंबोदर अभिव्यक्ति के रूप में:

((...args)=>args.reduce((a,b)=>a+b) / args.length)(1,2,3,4,5); // 3

मैं प्रसार ऑपरेटर को बहुत पसंद करता हूं। यह स्वच्छ और स्व-दस्तावेजीकरण है।


2
अपडेट किए गए उत्तर के लिए धन्यवाद, यह पोस्ट ES 2015 से पहले की है, इसलिए मुझे खुशी है कि आपने हाल ही के विकल्पों में भरा है
Fire Crow

5

इसे splatसंचालक कहा जाता है । आप इसका उपयोग जावास्क्रिप्ट में कर सकते हैं apply:

var arr = ['a','b','c','d'];
var func = function() {
    // debug 
    console.log(arguments.length);
    console.log(arguments);
}
func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(arr); // prints 1, then 'Array'
func.apply(null, arr); 

4

ES6 के साथ आप उपयोग कर सकते हैं बाकी पैरामीटर के लिए varagrs। यह तर्क सूची लेता है और इसे एक सरणी में परिवर्तित करता है।

function logArgs(...args) {
    console.log(args.length)
    for(let arg of args) {
        console.log(arg)
    }
}

2

यह चर तर्कों और पूर्णांक पर सरणी के लिए पूर्णांकों की गणना के लिए एक नमूना कार्यक्रम है। उम्मीद है की यह मदद करेगा।

var CalculateSum = function(){
    calculateSumService.apply( null, arguments );
}

var calculateSumService = function(){
    var sum = 0;

    if( arguments.length === 1){
        var args = arguments[0];

        for(var i = 0;i<args.length; i++){
           sum += args[i]; 
        }
    }else{
        for(var i = 0;i<arguments.length; i++){
           sum += arguments[i]; 
        }        
    }

     alert(sum);

}


//Sample method call

// CalculateSum(10,20,30);         

// CalculateSum([10,20,30,40,50]);

// CalculateSum(10,20);

1
कुछ नोट: 1. varएक function scopeचर घोषित करता है । नए letऔर constकीवर्ड (ES 2015) block scopeचर घोषित करते हैं। ईएस 2015 से पहले, हालांकि, चर को अभ्यास के मामले के रूप में अभी भी फ़ंक्शन के शीर्ष पर फहराया जाना चाहिए था। 2. किसी तर्क के रूप में किसी सरणी की आपकी गलत स्वीकृति के कारण आपका पूर्णांक मान दिए जाने पर टूट जाता है (प्रश्न वैरिएग पूछता है; सरणियों को तर्क के रूप में स्वीकार नहीं करता है) CalculateSum(6) -> 0:। (अगली पोस्ट में जारी)
ब्रैडेन बेस्ट

1
3. जैसे डिबग फ़ंक्शन का उपयोग न करें alert। वास्तव में, बस उपयोग नहीं करते alert/prompt/confirm, अवधि। console.logडिबगिंग के बजाय उपयोग करें । 4. फ़ंक्शन को returnआईएनजी मूल्य होना चाहिए , न कि alertआईएनजी। 5. PascalCaseजब तक यह डेटा के "प्रकार" को संदर्भित नहीं करता है तब तक बचें । यानी एक वर्ग। उपयोग camelCaseया under_scoreइसके बजाय। 4. आपको अपने कार्यों की घोषणा करने का तरीका पसंद नहीं है। var f = function(){ ... }तात्पर्य यह है कि आप इसे किसी बिंदु पर बदलना चाहते हैं , जो शायद आपका इरादा नहीं है। function name(){ ... }इसके बजाय पारंपरिक वाक्यविन्यास का उपयोग करें ।
ब्रैडेन बेस्ट

इन सभी आलोचनात्मक बिंदुओं को प्रदर्शित करने के लिए, यहाँ आपके उत्तर में फ़ंक्शन का बेहतर संस्करण है।
ब्रैडेन बेस्ट

2
(function(window) {
  var proxied = window.alert;
  window.alert = function() {
    return proxied.apply(window, arguments);
  };
}(this));

alert(13, 37);

1

उन लोगों के लिए जिन्हें एक फ़ंक्शन से दूसरे फ़ंक्शन के चर संख्या पास करने से पुनर्निर्देशित किया गया था (जो नहीं करना चाहिए इस प्रश्न के डुप्लिकेट के रूप में चिह्नित किया ):

यदि आप एक फ़ंक्शन को दूसरे फ़ंक्शन से चर संख्या में पास करने की कोशिश कर रहे हैं, तो जावास्क्रिप्ट 1.8.5 के बाद से आप बस apply()दूसरे फ़ंक्शन पर कॉल कर सकते हैं और argumentsपैरामीटर में पास कर सकते हैं:

var caller = function()
{
    callee.apply( null, arguments );
}

var callee = function()
{
    alert( arguments.length );
}

caller( "Hello", "World!", 88 ); // Shows "3".

नोट: पहला तर्क thisउपयोग करने के लिए पैरामीटर है। पासिंगnull फ़ंक्शन को किसी संदर्भ की विधि के बजाय वैश्विक संदर्भ से, यानी वैश्विक फ़ंक्शन के रूप में कॉल करेगा।

इस दस्तावेज़ के अनुसार , ECMAScript 5 विनिर्देश apply()ने कड़ाई से एरियर के बजाय किसी भी "सामान्य सरणी-जैसी वस्तु" को लेने के लिए विधि को फिर से परिभाषित किया । इस प्रकार, आप सीधे पास कर सकते हैंarguments दूसरे फ़ंक्शन में सूची ।

क्रोम में परीक्षण 28.0, सफारी 6.0.5, और IE 10. इसे JSFiddle के साथ आज़माएं


0

हाँ, आप चर सं। एक समारोह के लिए तर्क। आप उपयोग कर सकते हैंapply प्राप्त करने के लिए ।

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

var arr = ["Hi","How","are","you"];

function applyTest(){
    var arg = arguments.length;
    console.log(arg);
}

applyTest.apply(null,arr);

0

क्या आप अपने फ़ंक्शन को किसी सरणी तर्क या चर तर्क पर प्रतिक्रिया देना चाहते हैं? यदि उत्तरार्द्ध, कोशिश करें:

var func = function(...rest) {
  alert(rest.length);

  // In JS, don't use for..in with arrays
  // use for..of that consumes array's pre-defined iterator
  // or a more functional approach
  rest.forEach((v) => console.log(v));
};

लेकिन अगर आप एक सरणी तर्क को संभालना चाहते हैं

var fn = function(arr) {
  alert(arr.length);

  for(var i of arr) {
    console.log(i);
  }
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.