Function.prototype.apply()
الدالة Function.prototype.apply()
تستدعي دالةً وتضبط قيمة this
فيها إلى القيمة المعطية، وستُوفَّر الوسائط التي ستُمرَّر إليها كمصفوفة (أو كائن شبيه بالمصفوفات).
ملاحظة: صحيحٌ أنَّ البنية العامة لهذه الدالة تكاد تماثل بينة الدالة call()
، لكن الفرق الرئيسي بينهما هو أنَّ الدالة call()
تقبل قائمةً بالوسائط التي تُمرَّر إلى الدالة، بينما apply()
تقبل مصفوفةً واحدةً تحتوي على الوسائط.
البنية العامة
func.apply([thisArg, argsArray])
thisArg
وسيطٌ اختياري، وهو يُمثِّل قيمة المعامل this
التي ستُستعمل في الدالة func
، لاحظ أنَّ قيمة this
المُمرَّرة لا تعني بالضرورة أنَّها القيمة التي ستستخدمها الدالة؛ فلو لم يكن تنفيذ الدالة في نمط strict، فسيُستعاض عن القيمتين null
و undefined
بالكائن العام (global object)، وستُغلَّف القيم الأوليّة بكائنات.
argsArray
وسيطٌ اختياري، وهو مصفوفة أو كائن شبيه بالمصفوفات، يُحدِّد ما هي الوسائط التي ستُمرَّر إلى الدالة func
، ويمكن أن تكون قيمة هذا الوسيط هي null
أو undefined
إذا لم تكن هنالك وسائط يجب تمريرها إلى الدالة.
القيمة المعادة
القيمة المعادة نتيجة استدعاء الدالة المُحدَّدة مع قيمة this
والوسائط (إن وُجِدَت).
الوصف
يمكنك إسناد قيمة this
مختلفة عند استدعاء دالة موجودة مسبقًا؛ إذ يُشير المعامل this
إلى الكائن الحالي؛ أما عند استخدام apply
، فيمكننا كتابة دالة مرةً واحدةً ثم استدعاؤها في كائنٍ آخر، دون الحاجة إلى إعادة كتابة تلك الدالة في الكائن الجديد.
الدالة apply()
شبيهة جدًا بالدالة call()
، باستثناء نوع الوسائط التي تدعمه كلُّ واحدةٍ منهما. فيمكننا استخدام مصفوفة من الوسائط بدلًا من قائمة بها، فعند استخدام الدالة apply()
نستطيع استخدام مصفوفة مُنشَأة بالشكل المختصرة كما في func.apply(this, ['eat', 'bananas'])
أو كائن Array
كما في func.apply(this, new Array('eat', 'bananas'))
.
يمكنك أيضًا استخدام الكائن arguments
في المعامل argsArray
، إذ إنَّ الكائن arguments
هو متغيرٌ محليٌ موجودٌ ضمن الدوال، ويمكن استخدامه لتمرير جميع الوسائط المُمرَّرة إلى الكائن الذي سيستدعي الدالة. وبالتالي لا يُفترَض أن تعرف عدد الوسائط عند استخدام الدالة apply
.
وبدءًا من معيار ECMAScript 5.1 يمكننا استخدام أي كائن يشبه المصفوفات، مما يعني أنَّ سيملك الخاصية length
وتكون أسماء الخاصيات فيه أعدادًا صحيحةً تقع في المجال (0...length-1)
. فمثلًا يمكن استخدام الكائن الآتي: { 'length': 2, '0': 'eat', '1': 'bananas' }
.
أمثلة
استخدام الدالة apply
مع الدوال البانية
يمكننا استخدام apply
لإنشاء سلسلة من الدوال البانية (chain of constructors) لأحد الكائنات بما يشبه لغة Java، ففي المثال الآتي سنُنشِئ دالةً تتبع إلى الكائن Function
باسم construct
، وستسمح لنا هذه الدالة بتمرير كائن يشبه المصفوفات إلى الدوال البانية بدلًا من قائمة بالوسائط:
Function.prototype.construct = function(aArgs) {
var oNew = Object.create(this.prototype);
this.apply(oNew, aArgs);
return oNew;
};
مثال عن استخدام الدالة construct
السابقة:
function MyConstructor() {
for (var nProp = 0; nProp < arguments.length; nProp++) {
this['property' + nProp] = arguments[nProp];
}
}
var myArray = [4, 'Hello world!', false];
var myInstance = MyConstructor.construct(myArray);
console.log(myInstance.property1); // 'Hello world!'
console.log(myInstance instanceof MyConstructor); // 'true'
console.log(myInstance.constructor); // 'MyConstructor'
استخدام apply
مع الدوال المُضمَّنة في اللغة
يُسهِّل التوظيف الذكي للدالة apply
من استخدام الدوال المُضمَّنة في اللغة في بعض المهام، وتلك المهام كانت تتطلب كتابة حلقة تكرار للمرور على عناصر المصفوفة.
سنستخدم في المثال الآتي الدالة Math.max
و Math.min
معرفة أكبر وأصغر قيمة في مصفوفة:
// معرفة أكبر وأصغر قيمة في المصفوفة الآتية
var numbers = [5, 6, 2, 3, 7];
// استخدام الدالة apply
var max = Math.max.apply(null, numbers);
// وهذا يكافئ
// Math.max(numbers[0], ...)
// Math.max(5, 6, ...)
var min = Math.min.apply(null, numbers);
// استخدام حلقة تكرار تقليدية
max = -Infinity, min = +Infinity;
for (var i = 0; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
if (numbers[i] < min) {
min = numbers[i];
}
}
لكن اعلم أنَّ استخدامك للدالة apply
بهذه الطريقة يُعرِّضك لتجاوز الحد الأقصى لعدد الوسائط المُمرَّرة إلى دالةٍ ما في محرِّك JavaScript (الرقم الدقيق للعدد الأقصى للوسائط يختلف من محرّك إلى آخر، فمحرِّك JavaScriptCore يسمح بتمرير 65536 وسيطًا)، وعند تمرير وسائط عددها أكبر من الحد الأقصى الذي يقبله محرّك JavaScript فسترمي بعض المحركات استثناءً، لكن غيرها ستتجاهل الوسائط الزائدة.
فإذا افتراضنا أنَّ الحد الأقصى لعدد الوسائط في أحد المحركات هو أربعة وسائط (بالطبع يكون الحد الأقصى أكثر من ذلك بكثير)، فستكون الوسائط المُمرَّرة إلى الدالة في المثال السابق هي 5, 6, 2, 3
بدلًا من المصفوفة كاملةً.
إذا كانت المصفوفة التي ستُمرِّرها إلى الدالة كبيرة جدًا (بضعة آلاف من القيم)، فحاول تقسيمها إلى أقسام وتطبيق الدالة على تلك الأقسام:
function minOfArray(arr) {
var min = Infinity;
var QUANTUM = 32768;
for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
var submin = Math.min.apply(null,
arr.slice(i, Math.min(i+QUANTUM, len)));
min = Math.min(submin, min);
}
return min;
}
var min = minOfArray([5, 6, 2, 3, 7]);
دعم المتصفحات
الميزة | Chrome | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
الدعم الأساسي | نعم | نعم | نعم | نعم | نعم |
مصادر ومواصفات
- مسودة المعيار ECMAScript Latest Draft.
- معيار ECMAScript 2015 (6th Edition).
- معيار ECMAScript 5.1.
- معيار ECMAScript 3rd Edition.