معامل البقية Rest في JavaScript

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

يسمح معامل البقية (rest parameter) بتمثيل عدد غير مُحدِّد من الوسائط المُمرَّرة إلى دالةٍ ما كمصفوفة.

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

function f(a, b, ...theArgs) {
  // ...
}

الوصف

إذا أُسبِقَ آخر معامل من معاملات الدالة بثلاث نقط ... فسيصبح مصفوفةً التي تبدأ من 0 حتى theArgs.length التي تحمل قيم الوسائط التي مُرِّرَت إلى الدالة.

ففي الشيفرة الموجودة في القسم السابق، ستحمل المصفوفة theArgs قيمة الوسيط الثالث المُمرَّر إلى الدالة (لأنَّ أوّل وسيط سيرتبط بالمعامل a، وسيرتبط ثاني وسيط بالمعامل b) وكل ما يليه من الوسائط.

الفرق بين معامل البقية والكائن arguments

هنالك ثلاثة فروقات رئيسية بين معامل البقية (rest parameter) والكائن arguments:

  • ستُسنَد الوسائط التي لم يعطَ لها اسم إلى المصفوفة التي يُشير إليها معامل البقية، بينما يحتوي الكائن arguments على جميع الوسائط المُمرَّرة إلى الدالة.
  • الكائن arguments ليس مصفوفةً حقيقةً، لكن معامل البقية من نوع الكائنات Array، لذا يمكن تطبيق الدوال sort و map و forEach و pop عليه مباشرةً.
  • الكائن argument يملك خصائص تابعة له فقط (مثل الخاصية callee).

التحويل من استخدام الكائن arguments إلى معامل البقية

أُضيف معامل البقية لتقليل مقدار الشيفرة التي ليس لها حاجة والتي يجب استخدامها مع الكائن arguments:

// كنا نستخدم الشيفرة الآتية قبل معامل البقية
function f(a, b) {
  var args = Array.prototype.slice.call(arguments, f.length);

  // ...
}

// ما سبق يكافئ ما يلي

function f(a, b, ...args) {
  
}

تفكيك قيم معامل البقية

يمكن تفكيك معامل البقية، وهذا يعني أنَّ بياناته ستُسنَد إلى متغيرات منفصلة، راجع صفحة الإسناد بالتفكيك لمزيدٍ من المعلومات.

function f(...[a, b, c]) {
  return a + b + c;
}

f(1)          // NaN (b, c غير معرفة)
f(1, 2, 3)    // 6
f(1, 2, 3, 4) // 6 (لن يُفكَّك المعامل الرابع)

أمثلة

لمّا كان المعامل theArgs هو مصفوفة، فيمكن الحصول على عدد العناصر الموجودة فيه باستخدام الخاصية length:

function fun1(...theArgs) {
  console.log(theArgs.length);
}

fun1();  // 0
fun1(5); // 1
fun1(5, 6, 7); // 3

استخدمنا معامل البقية في المثال الآتي لجمع جميع الوسائط المُمرَّرة إلى الدالة -بعد الوسيط الأول- في مصفوفة، ثم ضُرِبَ كلُّ واحدٍ منها بقيمة الوسيط الأوّل ثم ستُعاد المصفوفة الناتجة:

function multiply(multiplier, ...theArgs) {
  return theArgs.map(function(element) {
    return multiplier * element;
  });
}

var arr = multiply(2, 1, 2, 3); 
console.log(arr); // [2, 4, 6]

المثال الآتي يُظهِر أنَّ الدوال التابعة للكائن Array يمكن استخدامها على معامل البقية، لكن لا يمكن استخدامها على الكائن arguments:

function sortRestArgs(...theArgs) {
  var sortedArgs = theArgs.sort();
  return sortedArgs;
}

console.log(sortRestArgs(5, 3, 7, 1)); // 1, 3, 5, 7

function sortArguments() {
  var sortedArgs = arguments.sort(); 
  return sortedArgs; // لن يُنفَّذ ذلك
}


console.log(sortArguments(5, 3, 7, 1)); // TypeError (arguments.sort is not a function)

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

function sortArguments() {
  var args = Array.from(arguments);
  var sortedArgs = args.sort();
  return sortedArgs;
}
console.log(sortArguments(5, 3, 7, 1)); // 1, 3, 5, 7

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

الميزة Chrome Firefox Internet Explorer Opera Safari
الدعم الأساسي 47 15 غير مدعومة 34 10
الإسناد بالتفكيك 49 52 غير مدعومة 36 ؟

على النقيض من متصفح IE، يدعم متصفح Edge هذه الميزة دعمًا أساسيًا (دون دعم الإسناد بالتفكيك) بدءًا من الإصدار 12.

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