أفضل طريقة لتحديد ما إذا لم يتم إرسال الوسيطة إلى وظيفة JavaScript

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

  •  03-07-2019
  •  | 
  •  

سؤال

لقد رأيت الآن طريقتين لتحديد ما إذا كان قد تم تمرير وسيطة إلى وظيفة JavaScript.أتساءل ما إذا كانت إحدى الطرق أفضل من الأخرى أم أنها سيئة الاستخدام فقط؟

 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);
}
هل كانت مفيدة؟

المحلول

وهناك عدة طرق مختلفة للتحقق مما إذا تم تمرير حجة على وظيفة. بالإضافة إلى اثنين من التي ذكرتها في سؤالك (الأصلي) - فحص 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
}

وهذا له سلبيات أن نية مبرمج ليست (بصريا) واضحة والاستخدامات "الأرقام السحرية '؛ ولذلك، فمن المحتمل أن يكون الخطأ عرضة.

نصائح أخرى

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

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"
};

هذه إحدى الحالات القليلة التي أجد فيها الاختبار:

if(! argument2) {  

}

يعمل بشكل جيد ويحمل المعنى الضمني الصحيح من الناحية النحوية.

(مع التقييد المتزامن الذي لن أسمح بقيمة فارغة مشروعة له argument2 والذي له معنى آخر؛ولكن هذا من شأنه أن يكون حقًا مربك.)

يحرر:

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

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

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

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

(أنا أعتبر هذا جانبًا سلبيًا خطيرًا في الطريقة التي يستخدم بها هؤلاء الأشخاص اللغات الديناميكية.في كثير من الأحيان، لا يرغب الأشخاص في التخلي عن جميع الاختبارات الثابتة، وينتهي بهم الأمر بتزويرها.)

لقد رأيت هذا بشكل أكثر وضوحًا عند مقارنة كود ActionScript 3 الشامل بكود جافا سكريبت الأنيق.يمكن أن يكون حجم AS3 3 أو 4 أضعاف حجم js، وأظن أن الموثوقية ليست أفضل على الأقل، فقط بسبب العدد (3-4X) من قرارات الترميز التي تم اتخاذها.

كما تقول، Shog9، YMMV.:د

وهناك اختلافات كبيرة. اسمحوا وضع في بعض حالات الاختبار:

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

ومع الطريقة الأولى تصفون، لن يؤدي إلا إلى الاختبار الثاني استخدام القيمة الافتراضية. والطريقة الثانية تتخلف جميع ولكن لأول مرة (كما JS سيتم تحويل undefined، null، 0، و"" في false منطقية. وإذا كنت لاستخدام أسلوب توم، لن يؤدي إلا إلى اختبار رابع استخدام الافتراضي!

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

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

في ES6 (ES2015) يمكنك استخدام افتراضي المعلمات

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

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

وأنا آسف، أنا غير قادر على التعليق لا يزال حتى الآن، وذلك للإجابة إجابة توم ... في جافا سكريبت (غير معروف! = فارغة) == كاذبة في الواقع أن وظيفة لن تعمل مع "لاغية"، يجب عليك استخدام "غير معروف"

ويمكن أن تكون مريحة للاقتراب كشف حجة عن طريق إثارة الدالة مع كائن من الخصائص الاختيارية:

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]; }
            }
        }
    }
}

لماذا لا تستخدم مشغل !!؟ هذا المشغل، وضعت قبل المتغير، تحويلها إلى منطقية (إذا كنت قد فهمت جيدا)، وبالتالي فإن !!undefined و!!null (وحتى !!NaN، والتي يمكن أن تكون مثيرة للاهتمام للغاية) عودة false.

وهنا هو exemple:

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

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

foo() //=> will log false

في بعض الاحيان قد تحتاج أيضا إلى التحقق من وجود نوع، خاصة إذا كنت تستخدم الدالة كما جالبة واضعة. التعليمة البرمجية التالية هي 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;
            }
        }
    }
}

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

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

وهذا ضروري يعني أنه إذا كانت قيمة value غير موجودة / مر - تعيينها إلى 0

.

وهوه بارد جدا!

وfnCalledFunction (PARAM1، PARAM2، window.YourOptionalParameter)

وإذا كان يتم استدعاء الدالة أعلاه من العديد من الأماكن وكنت متأكدا من تمرير معلمات 2 الأولى من كل مكان ولكن لست متأكدا حول المعلمة 3RD ثم يمكنك استخدام النافذة.

وسوف window.param3 التعامل إذا لم يتم تعريفه من أسلوب المتصل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top