क्या जावास्क्रिप्ट में एक फ़ंक्शन के लिए "असीमित" संस्करण की अनुमति देने का एक तरीका है?
उदाहरण:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
क्या जावास्क्रिप्ट में एक फ़ंक्शन के लिए "असीमित" संस्करण की अनुमति देने का एक तरीका है?
उदाहरण:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
जवाबों:
ज़रूर, बस arguments
वस्तु का उपयोग करें ।
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
arguments
एक विशेष "ऐरे-लाइक" ऑब्जेक्ट है, जिसका अर्थ है कि इसकी लंबाई है, लेकिन कोई अन्य फ़ंक्शन नहीं है। अधिक जानकारी के लिए developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… देखें , और यह उत्तर: stackoverflow.com/a/13145228/1766230
length
संपत्ति है। इसमें arguments
वस्तु शामिल है । यह जानते हुए भी, और यह विधि 'सरणी' की एक प्रतिconcat
लौटाती है जिस पर इसे कहा जाता है, हम arguments
वस्तु को एक वास्तविक सरणी में आसानी से बदल सकते हैं जैसे कि var args = [].concat.call(arguments)
:। कुछ लोग Array.prototype.concat.call
इसके बजाय उपयोग करना पसंद करते हैं , लेकिन मुझे पसंद है []
, वे छोटे और मीठे हैं!
[...arguments].join()
(अधिकांश) हाल के ब्राउज़रों में, आप इस वाक्यविन्यास के साथ चर संख्याओं को स्वीकार कर सकते हैं:
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
एक अन्य विकल्प एक संदर्भ वस्तु में अपने तर्कों को पारित करना है।
function load(context)
{
// do whatever with context.name, context.address, etc
}
और इसे इस तरह से उपयोग करें
load({name:'Ken',address:'secret',unused:true})
इसका यह फायदा है कि आप जितने चाहें उतने नामित तर्क जोड़ सकते हैं, और फ़ंक्शन उन्हें उपयोग कर सकता है (या नहीं) जैसा कि वह फिट देखता है।
context
कोड के साथ तर्क का निर्माण कर सकते हैं और इसे उपयोग करने से पहले इसे चारों ओर से पारित कर सकते हैं ।
मैं केन के जवाब से सबसे अधिक गतिशील होने के साथ सहमत हूं और मैं इसे एक कदम आगे ले जाना पसंद करता हूं। यदि यह एक फ़ंक्शन है जिसे आप कई बार विभिन्न तर्कों के साथ कहते हैं - मैं केन के डिज़ाइन का उपयोग करता हूं, लेकिन फिर डिफ़ॉल्ट मान जोड़ें:
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];
}
यह संदर्भ ऑब्जेक्ट को डिफॉल्ट्स के साथ मर्ज कर देगा और डिफॉल्ट्स के साथ आपकी ऑब्जेक्ट में किसी अपरिभाषित मान को भर देगा।
_.defaults()
विधि निर्दिष्ट और डिफ़ॉल्ट तर्कों को मर्ज करने का एक बहुत अच्छा विकल्प है।
रेस्ट पैरामीटर सिंटैक्स का उपयोग करना बेहतर होता है क्योंकि रामस्ट ने बताया।
function (a, b, ...args) {}
मैं सिर्फ कुछ अच्छी संपत्ति जोड़ना चाहता हूँ ... तर्क तर्क
- यह एक सरणी है, और तर्क जैसी कोई वस्तु नहीं है। यह आपको सीधे मानचित्र जैसे कार्यों को लागू करने की अनुमति देता है।
- इसमें सभी पैरामीटर शामिल नहीं हैं, लेकिन इसमें से केवल एक ही पास हुआ है। इस मामले में एग फ़ंक्शन (ए, बी, ... आर्ग्स) में तर्क 3 से तर्कों में शामिल हैं
जैसा कि पहले ही उल्लेख किया गया है, आप arguments
फ़ंक्शन मापदंडों के एक चर संख्या को पुनः प्राप्त करने के लिए ऑब्जेक्ट का उपयोग कर सकते हैं ।
यदि आप समान तर्कों के साथ किसी अन्य फ़ंक्शन को कॉल करना चाहते हैं, तो उपयोग करें apply
। आप arguments
किसी सरणी में कनवर्ट करके भी तर्कों को जोड़ या हटा सकते हैं । उदाहरण के लिए, यह फ़ंक्शन कंसोल में प्रवेश करने से पहले कुछ पाठ सम्मिलित करता है:
log() {
let args = Array.prototype.slice.call(arguments);
args = ['MyObjectName', this.id_].concat(args);
console.log.apply(console, args);
}
हालांकि मैं आम तौर पर सहमत हूं कि नामित तर्क दृष्टिकोण उपयोगी और लचीला है (जब तक कि आप उस आदेश की परवाह नहीं करते हैं, जिसमें मामले में तर्क सबसे आसान है), मुझे 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)
वैकल्पिक पैटर्न प्रदान करें। हालाँकि, मेरी बात अब भी कायम है: हर फंक्शन के इनवोकेशन के लिए अतिरिक्त ऑब्जेक्ट बनाना और डिफ़ॉल्ट वैल्यू के एक जोड़े को सेट करने के लिए महंगे लूप चलाना ओवरहेड की एक पागल राशि है।
जबकि @roufamatic ने तर्कों का उपयोग दिखाया था और @Ken ने उपयोग के लिए किसी ऑब्जेक्ट का एक शानदार उदाहरण दिखाया था, मुझे लगता है कि इस उदाहरण में जो चल रहा है उसे न तो सही मायने में संबोधित किया जा सकता है और न भविष्य के पाठकों को भ्रमित कर सकता है और न ही खराब व्यवहार के लिए प्रेरित कर सकता है क्योंकि यह स्पष्ट रूप से एक फ़ंक्शन नहीं बताता है। / विधि का तर्क / मापदंडों की एक चर राशि लेने का इरादा है।
function varyArg () {
return arguments[0] + arguments[1];
}
जब कोई अन्य डेवलपर आपके कोड को देख रहा है तो यह मान लेना बहुत आसान है कि यह फ़ंक्शन पैरामीटर नहीं लेता है। खासकर अगर उस डेवलपर की दलीलें निजी नहीं हैं कीवर्ड के । इस वजह से स्टाइल गाइडलाइन का पालन करना और सुसंगत होना एक अच्छा विचार है। मैं सभी उदाहरणों के लिए Google का उपयोग करूंगा।
आइए स्पष्ट रूप से बताएं कि एक ही फ़ंक्शन में परिवर्तनीय पैरामीटर हैं:
function varyArg (var_args) {
return arguments[0] + arguments[1];
}
ऐसा समय हो सकता है जब किसी ऑब्जेक्ट की आवश्यकता होती है क्योंकि यह डेटा मैप का एकमात्र स्वीकृत और माना जाने वाला सबसे अच्छा अभ्यास तरीका है। साहचर्य सरणियों पर डूब जाते हैं और हतोत्साहित किया जाता है।
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
जैसा कि उत्तर दिया गया है कि तर्क कीवर्ड वास्तव में एक वस्तु देता है। इस वजह से किसी भी विधि को आप किसी ऐरे के लिए उपयोग करना चाहते हैं, उसे कॉल करना होगा। इसका एक उदाहरण:
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
arguments
जब फ़ंक्शन अंदर हो तो उस ऑब्जेक्ट का उपयोग करें जिसमें पास किए गए सभी तर्कों तक पहुंच हो।
ज्ञात रहे कि केन के सुझाए गए गुणों के साथ ऑब्जेक्ट पास करना, प्रत्येक कॉल पर अस्थायी ऑब्जेक्ट को आवंटित करने और जारी करने की लागत को जोड़ता है। मूल्य या संदर्भ द्वारा सामान्य तर्क पारित करना आमतौर पर सबसे अधिक कुशल होगा। कई अनुप्रयोगों के लिए हालांकि प्रदर्शन महत्वपूर्ण नहीं है, लेकिन कुछ के लिए यह हो सकता है।