المعاملات الافتراضية للدوال في JavaScript

من موسوعة حسوب

معاملات الدالة الافتراضية (default function parameters) تسمح بتهيئة معاملات الدالة مع قيم افتراضية إن لم تُمرَّر لها قيمة أثناء استدعاء الدالة أو كانت القيمة المُمرَّرة هي undefined.

البنية العامة

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {
   statements
}

الوصف

تكون قيمة المعاملات الافتراضية في JavaScript هي undefined، لكن في بعض الحالات يكون من المفيد ضبط قيمة تلك المعاملات إلى قيمةٍ أخرى، وهنا تلعب المعاملات الافتراضية دورها.

في الماضي كانت الاستراتيجية العامة المتبعة لضبط قيم افتراضية لمعاملات الدالة هي اختبار قيم المعاملات في جسم الدالة وإسناد قيمة إليها إن كانت قيمتها هي undefined؛ ففي المثال الآتي لم توفَّر قيمة للمعامل b، لذا ستكون قيمته هي undefined، وعند تقدير قيمة التعبير a * b فستُعيد الدالة multiply القيمة NaN، لكننا تداركنا الأمر في السطر الثاني باختبار قيمة المعامل b:

function multiply(a, b) {
  b = (typeof b !== 'undefined') ?  b : 1;
  return a * b;
}

multiply(5, 2); // 10
multiply(5, 1); // 5
multiply(5);    // 5

لكن مع إضافة المعاملات الافتراضية في معيار ECMAScript 2015 (أي ES6)، فلم يعد التحقق من قيمة المعامل في جسم الدالة ضروريًا، إذ يمكننا الآن إضافة القيمة الافتراضية 1 في ترويسة الدالة كما في المثال الآتي:

function multiply(a, b = 1) {
  return a * b;
}

multiply(5, 2); // 10
multiply(5, 1); // 5
multiply(5);    // 5

أمثلة

أثر تمرير القيمة undefined وغيرها من القيم

استدعينا الدالة test في الشيفرة الآتية دون تمرير وسيط إليها، ومع تمرير القيمة undefined، ثم جربنا غير ذلك من القيم التي كانت ستُقدَّر قيمتها على أنها false؛ لاحظ قيمة المعامل num:

function test(num = 1) {
  console.log(typeof num);
}

test();          // 'number' (num : 1)
test(undefined); // 'number' (num : 1)

// تجربة القيم الأخرى
test('');        // 'string' (num : '')
test(null);      // 'object' (num : null)

تُقدَّر قيمة المعامل الافتراضية عند الاستدعاء

تُقدَّر قيم المعاملات الافتراضية عند كل استدعاء، أي أنَّ كائنًا جديدًا سيُنشَأ في كل مرة تُستدعى فيها الدالة، على النقيض من بعض لغات البرمجة مثل Python:

function append(value, array = []) {
  array.push(value);
  return array;
}

append(1); //[1]
append(2); //[2], NOT [1, 2]

وسينطبق المثل على الدوال والمتغيرات:

function callSomething(thing = something()) {
 return thing;
}

function something() {
  return 'sth';
}

callSomething();  //sth

قيمة المعاملات الافتراضية يمكن استخدامها في المعاملات الافتراضية التي تليها

لاحظ أنَّ بالإمكان استخدام قيمة المعاملات الافتراضية السابقة عند حساب قيمة قيمة أحد المعاملات الافتراضية:

function singularAutoPlural(singular, plural = singular + 's', 
                            rallyingCry = plural + ' ATTACK!!!') {
  return [singular, plural, rallyingCry]; 
}

//["Gecko","Geckos", "Geckos ATTACK!!!"]
singularAutoPlural('Gecko');

//["Fox","Foxes", "Foxes ATTACK!!!"]
singularAutoPlural('Fox', 'Foxes');

//["Deer", "Deer", "Deer ... peaceful."]
singularAutoPlural('Deer', 'Deer', 'Deer are peaceful.')

هذا السلوك سيساعد كثيرًا في تبسيط بنية الدالة، والمثال الآتي سيبيّن عدد الحالات التي يجب معالجتها إن لم تكن ميزة المعاملات الافتراضية موجودةً:

function go() {
  return ':P';
}

function withDefaults(a, b = 5, c = b, d = go(), e = this, 
                      f = arguments, g = this.value) {
  return [a, b, c, d, e, f, g];
}

function withoutDefaults(a, b, c, d, e, f, g) {
  switch (arguments.length) {
    case 0:
      a;
    case 1:
      b = 5;
    case 2:
      c = b;
    case 3:
      d = go();
    case 4:
      e = this;
    case 5:
      f = arguments;
    case 6:
      g = this.value;
    default:
  }
  return [a, b, c, d, e, f, g];
}

withDefaults.call({value: '=^_^='});
// [undefined, 5, 5, ":P", {value:"=^_^="}, arguments, "=^_^="]


withoutDefaults.call({value: '=^_^='});
// [undefined, 5, 5, ":P", {value:"=^_^="}, arguments, "=^_^="]

الإسناد بالتفكيك مع قيم المعاملات الافتراضية

يمكن استخدام الإسناد بالتفكيك (destructuring assignment) مع قيم المعاملات الافتراضية، كما في في المثال الآتي:

function f([x, y] = [1, 2], {z: z} = {z: 3}) { 
  return x + y + z; 
}

f(); // 6

دعم المتصفحات

الميزة Chrome Firefox Internet Explorer Opera Safari
الدعم الأساسي 49 15 غير مدعومة 45 10
معاملات دون قيم افتراضية بعد معاملات لها قيم افتراضية 49 26 غير مدعومة 45 10
الإسناد بالتفكيك 49 41 غير مدعومة ؟ ؟

على النقيض من متصفح IE، يدعم متصفح Edge هذه الميزة بدءًا من الإصدار 14.

مصادر ومواصفات