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


236

मैंने अब यह निर्धारित करने के लिए 2 तरीके देखे हैं कि क्या एक जावास्क्रिप्ट फ़ंक्शन को एक तर्क दिया गया है। मैं सोच रहा था कि क्या एक विधि दूसरे से बेहतर है या यदि एक का उपयोग करना बुरा है?

 function Test(argument1, argument2) {
      if (Test.arguments.length == 1) argument2 = 'blah';

      alert(argument2);
 }

 Test('test');

या

 function Test(argument1, argument2) {
      argument2 = argument2 || 'blah';

      alert(argument2);
 }

 Test('test');

जहाँ तक मैं बता सकता हूँ, वे दोनों एक ही चीज़ में परिणत होते हैं, लेकिन मैंने उत्पादन में पहले एक का ही उपयोग किया है।

टॉम द्वारा उल्लिखित एक अन्य विकल्प :

function Test(argument1, argument2) {
    if(argument2 === null) {
        argument2 = 'blah';
    }

    alert(argument2);
}

जुआन की टिप्पणी के अनुसार, टॉम के सुझाव को बदलना बेहतर होगा:

function Test(argument1, argument2) {
    if(argument2 === undefined) {
        argument2 = 'blah';
    }

    alert(argument2);
}

यह वास्तव में एक ही है। यदि आपके पास हमेशा तर्कों की एक स्थिर संख्या होती है, तो दूसरी विधि के साथ जाएं, अन्यथा तर्कों के उपयोग से इसे पुनरावृत्त करना संभव है।
लुका मैटिस

7
एक तर्क जो पारित नहीं हुआ था, अपरिभाषित के रूप में आता है। अशक्त के खिलाफ सख्त समानता के साथ परीक्षण विफल हो जाएगा। आपको अपरिभाषित के साथ सख्त समानता का उपयोग करना चाहिए।
जुआन मेंडेस

19
याद रखें: argument2 || 'blah';'blah' में परिणाम होगा अगर argument2है false, बस नहीं करता है, तो यह अनिर्धारित रहता है (!)। यदि argument2एक बूलियन है, और इसके लिए फ़ंक्शन पारित हो falseगया है, तो वह रेखा argument2ठीक से परिभाषित होने के बावजूद 'ब्लाह' लौटेगी
सैंडी गिफर्ड

9
@SandyGifford: वही समस्या है, तो argument2है 0, ''या null
रवि

@rvighne बहुत सच है। वस्तुओं और कास्टिंग की जावास्क्रिप्ट की अद्वितीय व्याख्या एक बार सबसे अच्छा और सबसे खराब भागों में है।
सैंडी गिफर्ड

जवाबों:


274

यह जांचने के कई अलग-अलग तरीके हैं कि क्या किसी फ़ंक्शन को एक तर्क दिया गया था। अपने (मूल) प्रश्न में आपके द्वारा बताए गए दो के अलावा - डिफ़ॉल्ट मान प्रदान करने के लिए ऑपरेटर की जाँच करना arguments.lengthया उसका उपयोग करना ||- एक के undefinedमाध्यम से argument2 === undefinedया typeof argument2 === 'undefined'यदि कोई व्यक्ति पागल है (टिप्पणियों को देखें) के लिए तर्कों की स्पष्ट रूप से जांच कर सकते हैं ।

का उपयोग करते हुए ||ऑपरेटर मानक अभ्यास हो गया है - सब शांत बच्चों को यह करना है - लेकिन सावधान रहें: डिफ़ॉल्ट मान है, तो तर्क मूल्यांकन करने के लिए ट्रिगर किया जाएगा false, जिसका अर्थ है कि यह वास्तव में हो सकता है undefined, null, false, 0, ''(या जिसके लिए कुछ और Boolean(...)रिटर्न false)।

तो सवाल यह है कि कब किस चेक का इस्तेमाल करना है, क्योंकि वे सभी अलग-अलग परिणाम देते हैं।

जाँच arguments.lengthकरना 'सबसे सही' व्यवहार को प्रदर्शित करता है, लेकिन एक से अधिक वैकल्पिक तर्क होने पर यह संभव नहीं है।

के लिए परीक्षण undefinedअगले 'सर्वश्रेष्ठ' है - यह केवल 'विफल' है यदि फ़ंक्शन को स्पष्ट रूप से एक undefinedमूल्य के साथ कहा जाता है , जिसे सभी संभावना में तर्क को छोड़ने के समान माना जाना चाहिए।

के उपयोग ||ऑपरेटर भले ही एक वैध तर्क प्रदान की जाती है डिफ़ॉल्ट मान का उपयोग ट्रिगर हो सकता है। दूसरी ओर, इसका व्यवहार वास्तव में वांछित हो सकता है।

संक्षेप में: यदि आप जानते हैं कि आप क्या कर रहे हैं तो इसका उपयोग करें!

मेरी राय में, ||अगर कोई एक से अधिक वैकल्पिक तर्क है और कोई भी एक वस्तु शाब्दिक रूप से नामांकित मापदंडों के लिए समाधान के रूप में पारित नहीं करना चाहता है, तो जाने का तरीका भी है।

arguments.lengthस्विच स्टेटमेंट के लेबल के माध्यम से गिरने से डिफ़ॉल्ट मान प्रदान करने का एक और अच्छा तरीका संभव है:

function test(requiredArg, optionalArg1, optionalArg2, optionalArg3) {
    switch(arguments.length) {
        case 1: optionalArg1 = 'default1';
        case 2: optionalArg2 = 'default2';
        case 3: optionalArg3 = 'default3';
        case 4: break;
        default: throw new Error('illegal argument count')
    }
    // do stuff
}

इसका नकारात्मक पक्ष यह है कि प्रोग्रामर का इरादा स्पष्ट नहीं है (नेत्रहीन) और 'मैजिक नंबर' का उपयोग करता है; यह संभवतः त्रुटि प्रवण है।


42
यदि कोई व्यक्ति "अपरिभाषित" परिभाषित करता है, तो आपको वास्तव में टाइपऑफ तर्क 2 === "अपरिभाषित" की जांच करनी चाहिए।
जेडब्ल्यू।

133
मैं एक नोटिस जोड़ूंगा - लेकिन क्या बीमार कमीने ऐसे काम करते हैं?
क्रिस्टोफ

12
अपरिभाषित वैश्विक अंतरिक्ष में एक चर है। वैश्विक स्कोप में उस वैरिएबल को स्थानीय स्कोप के वैरिएबल के मुकाबले देखना धीमा है। लेकिन सबसे तेज़ टाइपोफ़ एक्स === "अपरिभाषित" का उपयोग करना है
कुछ

5
दिलचस्प। दूसरी ओर, तुलना === अपरिभाषित स्ट्रिंग तुलना की तुलना में तेज हो सकती है। मेरे परीक्षणों से संकेत मिलता है कि आप सही हैं, हालांकि: x === अपरिभाषित की जरूरत है ~ टाइपएक्स x === 'अपरिभाषित' के 1.5x समय
क्रिस्टोफ

4
@ क्रिसटोफ: आपकी टिप्पणी पढ़ने के बाद, मैंने चारों ओर से पूछा। मैं यह साबित करने में सक्षम था कि सूचक की तुलना में स्ट्रिंग तुलना निश्चित रूप से (केवल) नहीं है क्योंकि एक विशाल स्ट्रिंग की तुलना में एक छोटे स्ट्रिंग की तुलना में अधिक समय लगता है। हालांकि, दो विशाल तारों की तुलना करना वास्तव में केवल तभी धीमा होता है जब वे संघनन के साथ निर्मित होते हैं, लेकिन वास्तव में तेजी से अगर दूसरे को पहले से असाइनमेंट के रूप में बनाया गया था। तो यह शायद एक पॉइंटर टेस्ट द्वारा काम करता है जिसके बाद अक्षर परीक्षण होता है। हां, मैं बकवास से भरा था :) मुझे ज्ञान देने के लिए धन्यवाद ...
जुआन मेंडेस

17

यदि आप jQuery का उपयोग कर रहे हैं, तो एक विकल्प जो अच्छा है (विशेष रूप से जटिल स्थितियों के लिए), jQuery के विस्तार विधि का उपयोग करना है

function foo(options) {

    default_options = {
        timeout : 1000,
        callback : function(){},
        some_number : 50,
        some_text : "hello world"
    };

    options = $.extend({}, default_options, options);
}

यदि आप फ़ंक्शन को कॉल करते हैं तो इस तरह:

foo({timeout : 500});

विकल्प चर तब होगा:

{
    timeout : 500,
    callback : function(){},
    some_number : 50,
    some_text : "hello world"
};

15

यह उन कुछ मामलों में से एक है जहां मुझे परीक्षण मिला है:

if(! argument2) {  

}

काफी अच्छी तरह से काम करता है और सही प्रभाव वाक्यविन्यास करता है।

(एक साथ प्रतिबंध के साथ कि मैं एक वैध शून्य मान की अनुमति नहीं दूंगा argument2जिसके कुछ अन्य अर्थ हैं; लेकिन यह वास्तव में भ्रमित करने वाला होगा।)

संपादित करें:

यह शिथिल-टाइप और दृढ़ता से टाइप की जाने वाली भाषाओं के बीच एक शैलीगत अंतर का बहुत अच्छा उदाहरण है; और एक शैलीगत विकल्प जो जावास्क्रिप्ट को हुकुम में रखता है।

मेरी व्यक्तिगत प्राथमिकता (अन्य प्राथमिकताओं के लिए कोई आलोचना नहीं है) अतिसूक्ष्मवाद है। कम कोड को कहना होगा, जब तक मैं सुसंगत और संक्षिप्त हूं, कम किसी और को मेरे अर्थ को सही ढंग से समझने के लिए मजबूर करना होगा।

उस वरीयता का एक निहितार्थ यह है कि मैं ऐसा नहीं करना चाहता हूं - यह उपयोगी नहीं लगता है - प्रकार-निर्भरता परीक्षणों का एक गुच्छा। इसके बजाय, मैं कोड बनाने का प्रयास करता हूं कि यह कैसा दिखता है इसका मतलब है; और केवल उसी चीज का परीक्षण करें जिसके लिए मुझे वास्तव में परीक्षण करने की आवश्यकता होगी।

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

(मुझे लगता है कि इन लोगों ने डायनेमिक भाषाओं का उपयोग करने के तरीके में एक गंभीर नकारात्मक पक्ष रखा है। अक्सर लोग सभी स्थिर परीक्षणों को छोड़ना नहीं चाहते हैं, और इसे समाप्त करना चाहते हैं।)

मैंने यह सबसे शानदार ढंग से व्यापक ActionScript 3 कोड को सुरुचिपूर्ण जावास्क्रिप्ट कोड के साथ तुलना करने में देखा है। AS3 js के थोक के 3 या 4 गुना हो सकता है, और मुझे संदेह है कि कम से कम कोई बेहतर नहीं है, बस कोडिंग निर्णयों की संख्या (3-4X) के कारण थे।

जैसा कि आप कहते हैं, शोग 9, वाईएमएमवी। : डी


1
if (बहस 2) तर्क 2 = 'डिफ़ॉल्ट' तर्क 2 = तर्क 2 के बराबर है || 'डिफ़ॉल्ट' - मुझे दूसरा संस्करण नेत्रहीन अधिक मनभावन लगता है ...
क्रिस्टोफ

5
और मुझे यह अधिक क्रियात्मक और विचलित करने वाला लगता है; लेकिन यह व्यक्तिगत प्राथमिकता है, मुझे यकीन है।
dkretz

4
@le dorfier: यह खाली तारों के उपयोग को भी रोकता है, 0, और बूलियन को गलत।
शोग

@le dorfier: सौंदर्यशास्त्र से परे, एक महत्वपूर्ण अंतर है: उत्तरार्द्ध प्रभावी रूप से निष्पादन का एक दूसरा रास्ता बनाता है, जो एक डिफ़ॉल्ट मान के सरल असाइनमेंट से परे व्यवहार को जोड़ने के लिए लापरवाह अनुचर को लुभा सकता है। YMMV, बिल्कुल।
शोग

3
क्या होगा अगर पैरामीटर 2 एक बूलियन === गलत है; या कोई फ़ंक्शन {झूठा वापस?}
फ्रेस्को

7

महत्वपूर्ण अंतर हैं। आइए कुछ परीक्षण मामलों को सेट करें:

var unused; // value will be undefined
Test("test1", "some value");
Test("test2");
Test("test3", unused);
Test("test4", null);
Test("test5", 0);
Test("test6", "");

आपके द्वारा वर्णित पहली विधि के साथ, केवल दूसरा परीक्षण डिफ़ॉल्ट मान का उपयोग करेगा। दूसरी विधि सभी लेकिन पहले लागू हो जाएगी (जैसा कि जे एस में परिवर्तित कर देंगे undefined, null, 0, और ""बूलियन में false। और अगर आप टॉम की विधि का उपयोग कर रहा है, केवल चौथे परीक्षण डिफ़ॉल्ट उपयोग करेगा!

वास्तव में आपके द्वारा चुनी गई विधि आपके इच्छित व्यवहार पर निर्भर करती है। यदि इसके अलावा अन्य मूल्य undefinedस्वीकार्य हैं argument2, तो आप संभवतः पहले से कुछ बदलाव चाहते हैं; यदि एक गैर-शून्य, गैर-शून्य, गैर-रिक्त मान वांछित है, तो दूसरी विधि आदर्श है - वास्तव में, यह अक्सर विचार से मूल्यों की इतनी विस्तृत श्रृंखला को जल्दी से समाप्त करने के लिए उपयोग किया जाता है।


7
url = url === undefined ? location.href : url;

नंगे हड्डियों का जवाब। कुछ स्पष्टीकरण दुख नहीं होगा।
पॉल रूनी

यह एक टर्नरी ऑपरेटर है जो स्पष्ट रूप से कहता है: यदि url अपरिभाषित (गायब) है, तो url वेरिएबल को स्थान पर सेट करें। Chrome (वर्तमान वेब पेज), अन्यथा निर्धारित url होने के लिए url वेरिएबल सेट करें।
rmooney

5

ES6 (ES2015) में आप डिफ़ॉल्ट मापदंडों का उपयोग कर सकते हैं

function Test(arg1 = 'Hello', arg2 = 'World!'){
  alert(arg1 + ' ' +arg2);
}

Test('Hello', 'World!'); // Hello World!
Test('Hello'); // Hello World!
Test(); // Hello World!


यह उत्तर वास्तव में दिलचस्प है और ऑप के लिए उपयोगी हो सकता है। हालांकि यह वास्तव में इस सवाल का जवाब नहीं देता है
उल्सिसे बीएन

जैसा कि मैं देख रहा हूँ - अगर वह परिभाषित नहीं था तो वह arg को परिभाषित करना चाहता है, इसलिए मैंने कुछ उपयोगी जानकारी पोस्ट की
Andriy2

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

4

मुझे क्षमा करें, मैं अभी भी टिप्पणी नहीं कर सकता, इसलिए टॉम के उत्तर का जवाब देने के लिए ... जावास्क्रिप्ट में (अपरिभाषित! = Null) == असत्य वास्तव में "null" के साथ काम नहीं करेगा, आपको "अपरिभाषित" का उपयोग करना चाहिए


1
और टॉम को एक गलत जवाब के लिए दो upvotes मिले - यह जानना हमेशा अच्छा होता है कि ये सामुदायिक सिस्टम कितने अच्छे हैं?)
क्रिस्टोफ

3

!!ऑपरेटर का उपयोग क्यों नहीं ? यह ऑपरेटर, चर से पहले रखा गया है, इसे बूलियन में बदल दें (यदि मैं अच्छी तरह से समझ गया हूं), तो !!undefinedऔर !!null(और यहां तक ​​कि !!NaN, जो काफी दिलचस्प हो सकता है) वापस आ जाएगा false

यहाँ एक छूट है:

function foo(bar){
    console.log(!!bar);
}

foo("hey") //=> will log true

foo() //=> will log false

बूलियन सच, शून्य और खाली स्ट्रिंग के साथ काम नहीं करता है। उदाहरण के लिए, फू (0); गलत लॉग करेगा, लेकिन foo (1) सही लॉग करेगा
rosell.dk

2

वैकल्पिक गुणों के ऑब्जेक्ट के साथ अपने फ़ंक्शन को खाली करके तर्क का पता लगाने के लिए सुविधाजनक हो सकता है:

function foo(options) {
    var config = { // defaults
        list: 'string value',
        of: [a, b, c],
        optional: {x: y},
        objects: function(param){
           // do stuff here
        }
    }; 
    if(options !== undefined){
        for (i in config) {
            if (config.hasOwnProperty(i)){
                if (options[i] !== undefined) { config[i] = options[i]; }
            }
        }
    }
}

2

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

this.setCurrent = function(value) {
  this.current = value || 0;
};

इसका आवश्यक अर्थ है कि यदि मान valueमौजूद नहीं है / पास है - इसे 0 पर सेट करें।

बहुत अच्छा हुह!


1
इसका वास्तव में अर्थ है "यदि valueइसके बराबर है false, तो इसे 0. पर सेट करें" यह एक सूक्ष्म लेकिन बहुत महत्वपूर्ण अंतर है।
चार्ल्स वुड

@CharlesWood मान पारित नहीं किया गया / वर्तमान का मतलब केवल झूठा है
मोहम्मद ज़मीर

1
ज़रूर, अगर यह आपके कार्य के लिए आवश्यकता पर फिट बैठता है। लेकिन अगर, उदाहरण के लिए, अपने पैरामीटर बूलियन है, तो trueऔर falseमान्य मान रहे हैं, और आप पैरामीटर सब पर पारित नहीं किया जाता है, जब (समारोह एक से अधिक पैरामीटर है, खासकर अगर) के लिए एक तिहाई व्यवहार कर सकते हैं।
चार्ल्स वुड

1
और मुझे यह स्वीकार करना चाहिए कि यह कंप्यूटर विज्ञान में एक बहुत बड़ा तर्क है और यह सिर्फ एक राय का मामला हो सकता है: D
चार्ल्स वुड

@CharlesWood पार्टी के लिए देर से आने के लिए खेद है। मेरा सुझाव है कि आप इन्हें उत्तर विकल्प में स्वयं जोड़ दें
मोहम्मद ज़मीर

1

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

class PrivateTest {
    constructor(aNumber) {
        let _aNumber = aNumber;

        //Privileged setter/getter with access to private _number:
        this.aNumber = function(value) {
            if (value !== undefined && (typeof value === typeof _aNumber)) {
                _aNumber = value;
            }
            else {
                return _aNumber;
            }
        }
    }
}

0
function example(arg) {
  var argumentID = '0'; //1,2,3,4...whatever
  if (argumentID in arguments === false) {
    console.log(`the argument with id ${argumentID} was not passed to the function`);
  }
}

क्योंकि सरणियाँ विरासत से मिली हैं Object.prototype। दुनिया को बेहतर बनाने के लिए the पर विचार करें।


-1

fnCalledFunction (Param1, Param2, window.YourOptionalParameter)

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

अगर यह कॉलर विधि से परिभाषित नहीं है, तो window.param3 हैंडल करेगा।

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