هل هناك طريقة أفضل للقيام بمعلمات الوظائف الاختيارية في JavaScript؟[ينسخ]

StackOverflow https://stackoverflow.com/questions/148901

  •  02-07-2019
  •  | 
  •  

سؤال

هذا السؤال لديه بالفعل إجابة هنا:

لقد تعاملت دائمًا مع المعلمات الاختيارية في JavaScript مثل هذا:

function myFunc(requiredArg, optionalArg){
  optionalArg = optionalArg || 'defaultValue';

  // Do stuff
}

هل هناك طريقة افضل لفعله؟

هل هناك أي حالات يتم فيها استخدام || مثل هذا سوف تفشل؟

هل كانت مفيدة؟

المحلول

يفشل المنطق الخاص بك إذا تم تمرير OptionArg، ولكن يتم تقييمه على أنه خطأ - جرب هذا كبديل

if (typeof optionalArg === 'undefined') { optionalArg = 'default'; }

أو لغة بديلة:

optionalArg = (typeof optionalArg === 'undefined') ? 'default' : optionalArg;

استخدم أي لغة توصل النية بشكل أفضل لك!

نصائح أخرى

في ECMAScript 2015 (المعروف أيضًا باسم "ES6")، يمكنك الإعلان عن قيم الوسيطات الافتراضية في إعلان الوظيفة:

function myFunc(requiredArg, optionalArg = 'defaultValue') {
    // do stuff
}

المزيد عنهم في هذه المقالة على MDN.

هذا حاليا مدعوم فقط من قبل فايرفوكس, ، ولكن مع اكتمال المعيار، توقع أن يتحسن الدعم بسرعة.

تحرير (2019-06-12):

يتم الآن دعم المعلمات الافتراضية على نطاق واسع بواسطة المتصفحات الحديثة.كافة إصدارات Internet Explorer لا تدعم هذه الميزة.ومع ذلك، فإن Chrome وFirefox وEdge يدعمونه حاليًا.

أجد أن هذه هي الطريقة الأبسط والأكثر قابلية للقراءة:

if (typeof myVariable === 'undefined') { myVariable = 'default'; }
//use myVariable here

إن إجابة بول ديكسون (في رأيي المتواضع) أقل قابلية للقراءة من هذا، ولكنها تعود إلى التفضيل.

تعتبر إجابة insin أكثر تقدمًا، ولكنها أكثر فائدة للوظائف الكبيرة!

تحرير 17/11/2013 الساعة 9:33 مساءً: لقد قمت بإنشاء حزمة لـ Node.js تسهل "التحميل الزائد" للوظائف (الطرق) التي تسمى حدودي.

إذا كنت بحاجة إلى تشاك الحرفي NULL في، فمن الممكن أن يكون لديك بعض المشاكل.وبصرف النظر عن ذلك، لا، أعتقد أنك ربما تكون على الطريق الصحيح.

الطريقة الأخرى التي يختارها بعض الأشخاص هي أخذ مصفوفة مساعدة من المتغيرات التي تتكرر من خلال قائمة الوسائط.يبدو الأمر أكثر إتقانًا بعض الشيء ولكني أتخيل أنه يتطلب عملية/ذاكرة أكثر قليلاً (قليلًا جدًا).

function myFunction (argArray) {
    var defaults = {
        'arg1'  :   "value 1",
        'arg2'  :   "value 2",
        'arg3'  :   "value 3",
        'arg4'  :   "value 4"
    }

    for(var i in defaults) 
        if(typeof argArray[i] == "undefined") 
               argArray[i] = defaults[i];

    // ...
}

من الناحية المثالية، يمكنك إعادة البناء لتمرير كائن و دمج باستخدام كائن افتراضي، لذا لا يهم الترتيب الذي يتم تمرير الوسائط به (راجع القسم الثاني من هذه الإجابة أدناه).

ومع ذلك، إذا كنت تريد شيئًا سريعًا وموثوقًا وسهل الاستخدام وغير ضخم، فجرّب ما يلي:


حل سريع ونظيف لأي عدد من الوسائط الافتراضية

  • إنه يتدرج بأناقة:الحد الأدنى من التعليمات البرمجية الإضافية لكل افتراضي جديد
  • يمكنك لصقه في أي مكان:فقط قم بتغيير عدد الوسائط والمتغيرات المطلوبة
  • إذا كنت تريد أن تمر undefined إلى وسيطة ذات قيمة افتراضية، وبهذه الطريقة، يتم تعيين المتغير كـ undefined.سيتم استبدال معظم الخيارات الأخرى في هذه الصفحة undefined مع القيمة الافتراضية.

فيما يلي مثال لتوفير الإعدادات الافتراضية لثلاث وسيطات اختيارية (مع وسيطتين مطلوبتين)

function myFunc( requiredA, requiredB,  optionalA, optionalB, optionalC ) {

  switch (arguments.length - 2) { // 2 is the number of required arguments
    case 0:  optionalA = 'Some default';
    case 1:  optionalB = 'Another default';
    case 2:  optionalC = 'Some other default';
    // no breaks between cases: each case implies the next cases are also needed
  }

}

عرض توضيحي بسيط.هذا مشابه ل إجابة روينفينج, ، ولكن يمكن تمديده بسهولة لأي عدد من الوسائط الافتراضية، وأسهل للتحديث، و استخدام arguments لا Function.arguments.


تمرير ودمج الكائنات لمزيد من المرونة

الكود أعلاه، مثل العديد من الطرق لتنفيذ الوسائط الافتراضية، لا يمكنه تمرير الوسائط خارج التسلسل، على سبيل المثال، تمرير optionalC لكن الرحيل optionalB ليعود إلى وضعه الافتراضي.

الخيار الجيد لذلك هو تمرير الكائنات ودمجها مع كائن افتراضي.يعد هذا أيضًا أمرًا جيدًا لقابلية الصيانة (فقط احرص على إبقاء التعليمات البرمجية الخاصة بك قابلة للقراءة، لذلك لن يُترك المتعاونون في المستقبل في حالة تخمين حول المحتويات المحتملة للكائنات التي تقوم بتمريرها).

مثال باستخدام jQuery.إذا كنت لا تستخدم jQuery، فيمكنك بدلاً من ذلك استخدام الشرطة السفلية _.defaults(object, defaults) أو تصفح هذه الخيارات:

function myFunc( args ) {
  var defaults = {
    optionalA: 'Some default',
    optionalB: 'Another default',
    optionalC: 'Some other default'
  };
  args = $.extend({}, defaults, args);
}

هنا مثال بسيط على ذلك في العمل.

يمكنك استخدام بعض المخططات المختلفة لذلك.لقد قمت دائمًا باختبار الحجج. الطول:

function myFunc(requiredArg, optionalArg){
  optionalArg = myFunc.arguments.length<2 ? 'defaultValue' : optionalArg;

  ...

-- عند القيام بذلك، من غير المحتمل أن يفشل، لكنني لا أعرف ما إذا كان طريقك لديه أي فرصة للفشل، الآن فقط لا أستطيع التفكير في سيناريو، حيث سيفشل بالفعل ...

ثم قدم بول سيناريو فاشلًا واحدًا!-)

على غرار إجابة أولي، أستخدم كائن وسيطة وكائن يحدد القيم الافتراضية.مع قليل من السكر...

/**
 * Updates an object's properties with other objects' properties. All
 * additional non-falsy arguments will have their properties copied to the
 * destination object, in the order given.
 */
function extend(dest) {
  for (var i = 1, l = arguments.length; i < l; i++) {
    var src = arguments[i]
    if (!src) {
      continue
    }
    for (var property in src) {
      if (src.hasOwnProperty(property)) {
        dest[property] = src[property]
      }
    }
  }
  return dest
}

/**
 * Inherit another function's prototype without invoking the function.
 */
function inherits(child, parent) {
  var F = function() {}
  F.prototype = parent.prototype
  child.prototype = new F()
  child.prototype.constructor = child
  return child
}

...يمكن جعل هذا أجمل قليلاً.

function Field(kwargs) {
  kwargs = extend({
    required: true, widget: null, label: null, initial: null,
    helpText: null, errorMessages: null
  }, kwargs)
  this.required = kwargs.required
  this.label = kwargs.label
  this.initial = kwargs.initial
  // ...and so on...
}

function CharField(kwargs) {
  kwargs = extend({
    maxLength: null, minLength: null
  }, kwargs)
  this.maxLength = kwargs.maxLength
  this.minLength = kwargs.minLength
  Field.call(this, kwargs)
}
inherits(CharField, Field)

ما الجميل في هذه الطريقة؟

  • يمكنك حذف أي عدد تريده من الوسيطات - إذا كنت تريد تجاوز قيمة وسيطة واحدة فقط، فيمكنك فقط توفير تلك الوسيطة، بدلاً من الاضطرار إلى المرور بشكل صريح undefined لنفترض أن هناك 5 وسيطات وتريد فقط تخصيص الوسيطة الأخيرة، كما سيتعين عليك القيام ببعض الطرق الأخرى المقترحة.
  • عند العمل مع دالة منشئة لكائن يرث من كائن آخر، فمن السهل قبول أي وسيطات مطلوبة من قبل منشئ الكائن الذي ترث منه، حيث لا يتعين عليك تسمية تلك الوسيطات في توقيع المنشئ الخاص بك، أو حتى توفير الإعدادات الافتراضية الخاصة بك (اسمح لمنشئ الكائن الأصلي بالقيام بذلك نيابةً عنك، كما هو موضح أعلاه متى CharField المكالمات Fieldمنشئ).
  • يمكن للكائنات التابعة في التسلسلات الهرمية للوراثة تخصيص الوسائط لمنشئها الأصل كما تراه مناسبًا، أو فرض قيمها الافتراضية أو التأكد من أن قيمة معينة سوف دائماً يستخدم.

إذا كنت تستخدم الإعدادات الافتراضية على نطاق واسع، فسيبدو هذا أكثر قابلية للقراءة:

function usageExemple(a,b,c,d){
    //defaults
    a=defaultValue(a,1);
    b=defaultValue(b,2);
    c=defaultValue(c,4);
    d=defaultValue(d,8);

    var x = a+b+c+d;
    return x;
}

فقط قم بإعلان هذه الوظيفة على النطاق العالمي.

function defaultValue(variable,defaultValue){
    return(typeof variable!=='undefined')?(variable):(defaultValue);
}

نمط الاستخدام fruit = defaultValue(fruit,'Apple');

* ملاحظة: يمكنك إعادة تسمية defaultValue وظيفة لاسم قصير، فقط لا تستخدم default إنها كلمة محجوزة في جافا سكريبت.

فحص النوع السائب

من السهل الكتابة، ولكن 0, '', false, null و undefined سيتم تحويلها إلى القيمة الافتراضية، والتي قد لا تكون النتيجة المتوقعة.

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
}

فحص صارم للنوع

أطول، ولكن يغطي غالبية الحالات.الحالة الوحيدة التي يتم فيها تعيين القيمة الافتراضية بشكل غير صحيح هي عندما نمرر undefined كمعلمة.

function myFunc(requiredArg, optionalArg) {
    optionalArg = typeof optionalArg !== 'undefined' ? optionalArg : 'defaultValue';
}

التحقق من متغيرات الوسائط

يلتقط جميع الحالات ولكنه الأكثر خرقاء في الكتابة.

function myFunc(requiredArg, optionalArg1, optionalArg2) {
    optionalArg1 = arguments.length > 1 ? optionalArg1 : 'defaultValue';
    optionalArg2 = arguments.length > 2 ? optionalArg2 : 'defaultValue';
}

ES6

لسوء الحظ، فإن دعم المتصفح ضعيف جدًا في الوقت الحالي

function myFunc(requiredArg, optionalArg = 'defaultValue') {

}

مع ES2015/ES6 يمكنك الاستفادة منها Object.assign والتي يمكن أن تحل محل $.extend() أو _.defaults()

function myFunc(requiredArg, options = {}) {
  const defaults = {
    message: 'Hello',
    color: 'red',
    importance: 1
  };

  const settings = Object.assign({}, defaults, options);

  // do stuff
}

يمكنك أيضًا استخدام الوسائط الافتراضية مثل هذا

function myFunc(requiredArg, { message: 'Hello', color: 'red', importance: 1 } = {}) {
  // do stuff
}

أنا معتاد على رؤية بعض الاختلافات الأساسية في التعامل مع المتغيرات الاختيارية.في بعض الأحيان، تكون الإصدارات المريحة مفيدة.

function foo(a, b, c) {
  a = a || "default";   // Matches 0, "", null, undefined, NaN, false.
  a || (a = "default"); // Matches 0, "", null, undefined, NaN, false.

  if (b == null) { b = "default"; } // Matches null, undefined.

  if (typeof c === "undefined") { c = "default"; } // Matches undefined.
}

الافتراضي الخاطئ المستخدم مع المتغير a على سبيل المثال، يتم استخدامه على نطاق واسع في العمود الفقري.js.

إذا كنت تستخدم تسطير أسفل السطر المكتبة (يجب عليك، إنها مكتبة رائعة):

_.defaults(optionalArg, 'defaultValue');

هبطت على هذا السؤال، والبحث عن المعلمات الافتراضية في EcmaScript 2015, ، وبالتالي مجرد ذكر ...

مع ES6 يمكننا القيام به المعلمات الافتراضية:

function doSomething(optionalParam = "defaultValue"){
    console.log(optionalParam);//not required to check for falsy values
}

doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"

خلال أحد المشروعات، لاحظت أنني كنت أكرر نفسي كثيرًا مع المعلمات والإعدادات الاختيارية، لذلك قمت بإنشاء فصل دراسي يتعامل مع فحص النوع ويعين قيمة افتراضية تؤدي إلى كود أنيق وقابل للقراءة.انظر المثال واسمحوا لي أن أعرف إذا كان هذا يناسبك.

var myCar           = new Car('VW', {gearbox:'automatic', options:['radio', 'airbags 2x']});
var myOtherCar      = new Car('Toyota');

function Car(brand, settings) {
    this.brand      = brand;

    // readable and adjustable code
    settings        = DefaultValue.object(settings, {});
    this.wheels     = DefaultValue.number(settings.wheels, 4);
    this.hasBreaks  = DefaultValue.bool(settings.hasBreaks, true);
    this.gearbox    = DefaultValue.string(settings.gearbox, 'manual');
    this.options    = DefaultValue.array(settings.options, []);

    // instead of doing this the hard way
    settings        = settings || {};
    this.wheels     = (!isNaN(settings.wheels)) ? settings.wheels : 4;
    this.hasBreaks  = (typeof settings.hasBreaks !== 'undefined') ? (settings.hasBreaks === true) : true;
    this.gearbox    = (typeof settings.gearbox === 'string') ? settings.gearbox : 'manual';
    this.options    = (typeof settings.options !== 'undefined' && Array.isArray(settings.options)) ? settings.options : [];
}

باستخدام هذه الفئة:

(function(ns) {

    var DefaultValue = {

        object: function(input, defaultValue) {
            if (typeof defaultValue !== 'object') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? input : defaultValue;
        },

        bool: function(input, defaultValue) {
            if (typeof defaultValue !== 'boolean') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (input === true) : defaultValue;
        },

        number: function(input, defaultValue) {
            if (isNaN(defaultValue)) throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined' && !isNaN(input)) ? parseFloat(input) : defaultValue;
        },

        // wrap the input in an array if it is not undefined and not an array, for your convenience
        array: function(input, defaultValue) {
            if (typeof defaultValue === 'undefined') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (Array.isArray(input) ? input : [input]) : defaultValue;
        },

        string: function(input, defaultValue) {
            if (typeof defaultValue !== 'string') throw new Error('invalid defaultValue type');
            return (typeof input === 'string') ? input : defaultValue;
        },

    };

    ns.DefaultValue = DefaultValue;

}(this));

لا أعرف سبب التصويت السلبي لرد @Paul، لكن التحقق من الصحة ضده null هو خيار جيد.ربما يكون المثال الأكثر إيجابية منطقيًا بشكل أفضل:

في JavaScript، تشبه المعلمة المفقودة المتغير المعلن الذي لم تتم تهيئته (فقط var a1;).ويقوم عامل المساواة بتحويل غير المحدد إلى null، لذلك يعمل هذا بشكل رائع مع كل من أنواع القيم والكائنات، وهذه هي الطريقة التي يتعامل بها CoffeeScript مع المعلمات الاختيارية.

function overLoad(p1){
    alert(p1 == null); // Caution, don't use the strict comparison: === won't work.
    alert(typeof p1 === 'undefined');
}

overLoad(); // true, true
overLoad(undefined); // true, true. Yes, undefined is treated as null for equality operator.
overLoad(10); // false, false


function overLoad(p1){
    if (p1 == null) p1 = 'default value goes here...';
    //...
}

رغم ذلك، هناك مخاوف من أن أفضل الدلالات هي typeof variable === 'undefined' أفضل قليلا.لست على وشك الدفاع عن هذا نظرًا لأن الأمر يتعلق بواجهة برمجة التطبيقات الأساسية وكيفية تنفيذ الوظيفة؛لا ينبغي أن يثير اهتمام مستخدم واجهة برمجة التطبيقات (API).

يجب أن أضيف أيضًا أن هذه هي الطريقة الوحيدة للتأكد فعليًا من فقدان أي وسيطة، وذلك باستخدام in عامل التشغيل الذي للأسف لن يعمل مع أسماء المعلمات، لذا يتعين عليه تمرير فهرس لـ arguments.

function foo(a, b) {
    // Both a and b will evaluate to undefined when used in an expression
    alert(a); // undefined
    alert(b); // undefined

    alert("0" in arguments); // true
    alert("1" in arguments); // false
}

foo (undefined);

اختبار غير محدد غير ضروري وليس قويًا بقدر ما يمكن أن يكون لأنه، كما أشار user568458، يفشل الحل المقدم إذا تم تمرير null أو false.قد يعتقد مستخدمو واجهة برمجة التطبيقات (API) الخاصة بك أن القيمة false أو null ستجبر الطريقة على تجنب تلك المعلمة.

function PaulDixonSolution(required, optionalArg){
   optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
   console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);

النتيجه هي:

defaultValue
provided
null
false

من المحتمل أن يكون هذان الأخيران سيئين.بدلاً من ذلك حاول:

function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

مما يؤدي إلى:

defaultValue
provided
defaultValue
defaultValue

السيناريو الوحيد الذي لا يكون فيه هذا هو الأمثل هو عندما يكون لديك بالفعل معلمات اختيارية من المفترض أن تكون منطقية أو فارغة مقصودة.

لقد جربت بعض الخيارات المذكورة هنا واختبرها الأداء.في هذه اللحظة يبدو أن المنطقي هو الأسرع.على الرغم من أن هذا يخضع للتغيير بمرور الوقت (إصدارات مختلفة من محركات JavaScript).

هذه هي نتائجي (Microsoft Edge 20.10240.16384.0):

Function executed            Operations/sec     Statistics
TypeofFunction('test');          92,169,505     ±1.55%   9% slower
SwitchFuntion('test');            2,904,685     ±2.91%  97% slower
ObjectFunction({param1: 'test'});   924,753     ±1.71%  99% slower
LogicalOrFunction('test');      101,205,173     ±0.92%     fastest
TypeofFunction2('test');         35,636,836     ±0.59%  65% slower

يمكن تكرار اختبار الأداء هذا بسهولة على:http://jsperf.com/اختياري-parameters-typeof-vs-switch/2

وهذا هو كود الاختبار:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        function TypeofFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 = (typeof optParam1 === "undefined") ? "Some default" : optParam1;
            optParam2 = (typeof optParam2 === "undefined") ? "Another default" : optParam2;
            optParam3 = (typeof optParam3 === "undefined") ? "Some other default" : optParam3;
        }

        function TypeofFunction2(param1, optParam1, optParam2, optParam3) {
            optParam1 = defaultValue(optParam1, "Some default");
            optParam2 = defaultValue(optParam2, "Another default");
            optParam3 = defaultValue(optParam3, "Some other default");
        }

        function defaultValue(variable, defaultValue) {
            return (typeof variable !== 'undefined') ? (variable) : (defaultValue);
        }

        function SwitchFuntion(param1, optParam1, optParam2, optParam3) {
            switch (arguments.length - 1) { // <-- 1 is number of required arguments
                case 0:
                    optParam1 = 'Some default';
                case 1:
                    optParam2 = 'Another default';
                case 2:
                    optParam3 = 'Some other default';
            }
        }

        function ObjectFunction(args) {
            var defaults = {
                optParam1: 'Some default',
                optParam2: 'Another default',
                optParam3: 'Some other default'
            }
            args = $.extend({}, defaults, args);
        }

        function LogicalOrFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 || (optParam1 = 'Some default');
            optParam2 || (optParam1 = 'Another default');
            optParam3 || (optParam1 = 'Some other default');
        }
    };
</script>

وهذا ما انتهى بي الأمر:

function WhoLikesCake(options) {
  options = options || {};
  var defaultOptions = {
    a : options.a || "Huh?",
    b : options.b || "I don't like cake."
  }
  console.log('a: ' + defaultOptions.b + ' - b: ' + defaultOptions.b);

  // Do more stuff here ...
}

دعا مثل هذا:

WhoLikesCake({ b : "I do" });

يا قوم -

بعد الاطلاع على هذه الحلول وغيرها، جربت عددًا منها باستخدام مقتطف من التعليمات البرمجية أصلاً من W3Schools كقاعدة.يمكنك العثور على ما يعمل في ما يلي.يعمل كل عنصر من العناصر التي تم التعليق عليها أيضًا، وهي طريقة تسمح لك بالتجربة ببساطة عن طريق إزالة التعليقات الفردية.لكي نكون واضحين، فإن معلمة "eyecolor" هي التي لم يتم تعريفها.

function person(firstname, lastname, age, eyecolor)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
this.eyecolor = eyecolor;
// if(null==eyecolor)
//   this.eyecolor = "unknown1";
//if(typeof(eyecolor)==='undefined') 
//   this.eyecolor = "unknown2";
// if(!eyecolor)
//   this.eyecolor = "unknown3";
this.eyecolor = this.eyecolor || "unknown4";
}

var myFather = new person("John", "Doe", 60);
var myMother = new person("Sally", "Rally", 48, "green");

var elem = document.getElementById("demo");
elem.innerHTML = "My father " +
              myFather.firstname + " " +
              myFather.lastname + " is " +
              myFather.age + " with " +
              myFather.eyecolor + " eyes.<br/>" +
              "My mother " +
              myMother.firstname + " " +
              myMother.lastname + " is " +
              myMother.age + " with " +
              myMother.eyecolor + " eyes."; 
function Default(variable, new_value)
{
    if(new_value === undefined) { return (variable === undefined) ? null : variable; }
    return (variable === undefined) ? new_value : variable;
}

var a = 2, b = "hello", c = true, d;

var test = Default(a, 0),
test2 = Default(b, "Hi"),
test3 = Default(c, false),
test4 = Default(d, "Hello world");

window.alert(test + "\n" + test2 + "\n" + test3 + "\n" + test4);

http://jsfiddle.net/mq60hqrf/

هنا هو الحل الخاص بي.مع هذا يمكنك ترك أي معلمة تريدها.ترتيب المعلمات الاختيارية ليس مهمًا ويمكنك إضافة التحقق المخصص.

function YourFunction(optionalArguments) {
            //var scope = this;

            //set the defaults
            var _value1 = 'defaultValue1';
            var _value2 = 'defaultValue2';
            var _value3 = null;
            var _value4 = false;

            //check the optional arguments if they are set to override defaults...
            if (typeof optionalArguments !== 'undefined') {

                if (typeof optionalArguments.param1 !== 'undefined')
                    _value1 = optionalArguments.param1;

                if (typeof optionalArguments.param2 !== 'undefined')
                    _value2 = optionalArguments.param2;

                if (typeof optionalArguments.param3 !== 'undefined')
                    _value3 = optionalArguments.param3;

                if (typeof optionalArguments.param4 !== 'undefined')
                    //use custom parameter validation if needed, in this case for javascript boolean
                   _value4 = (optionalArguments.param4 === true || optionalArguments.param4 === 'true');
            }

            console.log('value summary of function call:');
            console.log('value1: ' + _value1);
            console.log('value2: ' + _value2);
            console.log('value3: ' + _value3);
            console.log('value4: ' + _value4);
            console.log('');
        }


        //call your function in any way you want. You can leave parameters. Order is not important. Here some examples:
        YourFunction({
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
            param3: 'yourGivenValue3',
            param4: true,
        });

        //order is not important
        YourFunction({
            param4: false,
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
        });

        //uses all default values
        YourFunction();

        //keeps value4 false, because not a valid value is given
        YourFunction({
            param4: 'not a valid bool'
        });
  1. arg || 'default' هي طريقة رائعة وتصلح لـ 90% من الحالات

  2. يفشل عندما تحتاج إلى تمرير قيم قد تكون "خاطئة"

    • false
    • 0
    • NaN
    • ""

    في هذه الحالات، ستحتاج إلى أن تكون أكثر إسهابًا وأن تتحقق من ذلك undefined

  3. كن حذرًا أيضًا عندما يكون لديك وسائط اختيارية أولاً، عليك أن تكون على دراية بأنواع جميع الوسائط الخاصة بك

في جميع الحالات التي تكون فيها OptionArg خاطئة، سينتهي بك الأمر بقيمة defaultValue.

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
    console.log(optionalArg);
    // Do stuff
}
myFunc(requiredArg);
myFunc(requiredArg, null);
myFunc(requiredArg, undefined);
myFunc(requiredArg, "");
myFunc(requiredArg, 0);
myFunc(requiredArg, false);

كل القيمة الافتراضية للسجل أعلاه، لأن الستة كلها خاطئة.في الحالة 4، 5، 6، قد لا تكون مهتمًا بتعيين OptionArg كقيمة افتراضية، ولكنها تحدد لأنها خاطئة.

صحح لي إذا كنت مخطئًا، ولكن يبدو أن هذه هي الطريقة الأبسط (لحجة واحدة، على أي حال):

function myFunction(Required,Optional)
{
    if (arguments.length<2) Optional = "Default";
    //Your code
}

تلك أقصر من إصدار المشغل typeof.

function foo(a, b) {
    a !== undefined || (a = 'defaultA');
    if(b === undefined) b = 'defaultB';
    ...
}

أقترح عليك استخدام ArgueJS من هنا:

function myFunc(){
  arguments = __({requiredArg: undefined, optionalArg: [undefined: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

يمكنك أيضًا استبدال undefined حسب نوع الوسيطة التي تتوقع تلقيها، مثل هذا:

function myFunc(){
  arguments = __({requiredArg: Number, optionalArg: [String: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

ويبدو أن الطريقة الأكثر أمانا - للتعامل مع كافة \ أي أنواع كاذبة من الموردة الحجج قبل أن تقرر استخدام تقصير - هو التحقق من وجود\وجود حجة اختيارية في الدالة التي تم استدعاؤها

بالاعتماد على إنشاء عضو كائن الوسائط الذي لا يتم إنشاؤه حتى إذا كانت الوسيطة مفقودة، بغض النظر عن حقيقة أنه قد يتم الإعلان عنها، يمكننا كتابة وظيفتك على النحو التالي:

  function myFunc(requiredArg, optionalArg){
        optionalArg = 1 in arguments ? optionalArg : 'defaultValue';
  //do stuff
  }

الاستفادة من هذا السلوك:يمكننا التحقق بأمان من وجود أي قيم مفقودة في قائمة الوسائط بشكل تعسفي وصريح عندما نحتاج إلى التأكد من حصول الوظيفة على قيمة معينة مطلوبة في إجراءاتها.

في الكود التجريبي التالي سنضع عمدا بلا نوع و عديم القيمة غير معرف كقيمة افتراضية لتتمكن من تحديد ما إذا كانت قد تفشل في قيم الوسيطات الخاطئة، مثل 0 خطأ وما إلى ذلك، أو إذا كانت تتصرف كما هو متوقع.

function argCheck( arg1, arg2, arg3 ){

       arg1 = 0 in arguments || undefined;
       arg2 = 1 in arguments || false;
       arg3 = 2 in arguments || 0;
   var arg4 = 3 in arguments || null;

   console.log( arg1, arg2, arg3, arg4 ) 
}

الآن، يتم التحقق من بعض قيم الوسيطات الزائفة لمعرفة ما إذا كان وجودها قد تم اكتشافه بشكل صحيح وبالتالي يتم تقييمه حقيقي:

argCheck( "", 0, false, null );
>> true true true true

مما يعني - أنهم لم يفشلوا في التعرف على/كقيم الوسيطة المتوقعة.لدينا هنا فحص مع فقدان جميع الوسائط، والتي وفقًا لخوارزميتنا يجب أن تكتسب قيمها الافتراضية حتى لو كانت كذلك كاذبة.

argCheck( );
>> undefined false 0 null

كما نرى، الحجج arg1، arg2، arg3 وغير المعلنة arg4, ، يعودون بالضبط تقصير القيم، كما أمرت.ولأننا تأكدنا الآن من أنها تعمل، يمكننا إعادة كتابة الدالة التي ستكون قادرة بالفعل على استخدامها كما في المثال الأول باستخدام:أيضاً لو أو أ ثلاثي حالة.

في الوظائف التي تحتوي على أكثر من وسيطة اختيارية، ربما يكون تكرار التكرار قد أنقذنا من بعض البتات.ولكن منذ الحجة أسماء لا تتم تهيئتها إذا لم يتم توفير قيمها، فلن نتمكن من الوصول إليها عن طريق الأسماء بعد الآن حتى لو كتبنا قيمة افتراضية برمجيًا، فلا يمكننا الوصول إليها إلا عن طريق الحجج[فهرس] والتي لا فائدة منها في قراءة التعليمات البرمجية الحكيمة.

ولكن بصرف النظر عن هذا الإزعاج، والذي قد يكون مقبولًا تمامًا في بعض مواقف التشفير، هناك مشكلة أخرى غير محسوبة تتعلق بعدد متعدد وتعسفي من الإعدادات الافتراضية للوسيطات.والذي يمكن وينبغي اعتباره خطأً، حيث لم يعد بإمكاننا تخطي الوسائط، كما كان من الممكن أن نفعل ذلك ذات مرة، دون إعطاء قيمة، في بناء جملة مثل:

argCheck("a",,22,{});

لأنه سوف يرمي!مما يجعل من المستحيل بالنسبة لنا أن نستبدل حجتنا بحجة محددة كاذبة نوع القيمة الافتراضية المطلوبة لدينا.وهو غبي، منذ كائن الحجج هو كائن يشبه المصفوفة ومن المتوقع أن يدعم بناء الجملة والاصطلاح هذا كما هو، أصليًا أو افتراضيًا!

بسبب هذا القرار قصير النظر، لم يعد بإمكاننا أن نأمل في كتابة دالة مثل هذه:

function argCheck( ) {
    var _default = [undefined, 0, false, null ],
        _arg = arguments;

 for( var x in _default ) {
         x in _arg ? 1 : _arg[x] = _default[x];
        }
    console.log( _arg[0],_arg[1],_arg[2],_arg[3] );
}

في هذه الحالة، سنكون قادرين على كتابة كل قيمة افتراضية من النوع المطلوب في صف الوسائط وسنتمكن على الأقل من الوصول إليها عن طريق args.index.

على سبيل المثال، قد ينتج عن استدعاء الوظيفة هذا:

argCheck();
>>undefined 0 false null

كما هو محدد في مجموعة قيم الوسائط الافتراضية لدينا.ومع ذلك، لا يزال من الممكن القيام بما يلي:

argCheck({})
>>Object {  } 0 false null

argCheck({}, [])
>>Object {  } Array [  ] false null

ولكن مع الأسف لا:

 argCheck("a",,,22);
 >>SyntaxError: expected expression, got ','

والتي من شأنها أن يتم تسجيلها بطريقة أخرى:

>>a 0 false 22

ولكن هذا في عالم أفضل!ومع ذلك - بالنسبة للسؤال الأصلي - فإن الوظيفة العليا ستعمل بشكل جيد.على سبيل المثال:

function argCheck( arg, opt ) {
         1 in arguments ? 1 : opt = "default";
         console.log( arg, opt );
}

ملاحظة.:آسف لعدم الحفاظ على أنواع من الإعدادات الافتراضية المختارة في مدخلات الوسيطة الخاصة بي أثناء كتابتها.

function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top