المعاملات الافتراضية للدوال في 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.
مصادر ومواصفات
- مسودة المعيار ECMAScript Latest Draft.
- معيار ECMAScript 2015 (6th Edition).