Function.prototype.bind()
الدالة Function.prototype.bind()
تُنشِئ دالةً جديدةً التي عند استدعائها ستُضبَط قيمة المعامل this
إلى القيمة المعطية، وستُوفَّر إليها قائمة المعاملات التي تلي قيمة المعامل this
.
البنية العامة
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg
وسيطٌ يُمثِّل قيمة المعامل this
التي ستُستعمل في الدالة func
عند استدعائها، لاحظ أنَّ JavaScript ستتجاهل هذه القيمة إذا استدعيت الدالة كدالة بانية باستخدام المعامل new
.
arg1, arg2, ...
الوسائط التي ستُرفَق مع الوسائط المُمرَّرة إلى الدالة عند استدعائها.
القيمة المعادة
نسخة من الدالة المعطية مع قيمة this
المُخصَّصة والوسائط (إن وُجِدَت).
الوصف
الدالة bind()
تُنشِئ ما يسمى bound function (اختصارًا BF)، و BF هي exotic function object (هذه المصطلحات مأخوذة من معيار ECMAScript 2015 وآثرنا ذكرها كما هي) التي تغلِّف (wraps) كائن الدالة الأصلي.
استدعاء BF يؤدي إلى استدعاء الدالة المُغلَّفة. وتملك BF الخاصيات الداخلية الآتية:
[[BoundTargetFunction]]
: كائن الدالة المُغلَّف.[[BoundThis]]
: القيمة التي تُمرَّر كقيمة المعاملthis
عند استخدام الدالة المُغلَّفة.[[BoundArguments]]
: قائمة بالقيم التي ستُمرَّر كأوّل وسائط لأيّ استدعاء للدالة المُغلَّفة.[[Call]]
: تنفيذ الشيفرة المرتبطة بالكائن.
عند استدعاء bound function، فستستدعي الدالة الداخلية [[Call]]
على [[BoundTargetFunction]]
، مع الوسائط الآتية Call(boundThis, args)
، إذ إنَّ قيمة boundThis
هي [[BoundThis]]
و args
هي [[BoundArguments]]
متبوعةً بالوسائط المُمرَّرة إلى الدالة التي جرى استدعاؤها.
أمثلة
إنشاء bound function
أبسط استخدام للدالة bind
هي إنشاء دالة التي ستُستخدَم فيها قيمة this
معيّنة بغض النظر عن كيفية استدعائها.
خطأٌ شائعٌ يرتكبه مبرمجو JavaScript الجدد هو استخراج دالة من كائن، ثم استدعاء تلك الدالة لاحقًا مع توقع أنَّ تلك الدالة ستستخدم الكائن الأصلي كقيمة للمعامل this
؛ لكن ما لم نتخذ إجراءات معيّنة، فإنَّ الكائن الأصلي لن يعود مرتبطًا بالدالة. إنشاء bound function من تلك الدالة -التي تستخدم الكائن الأصلي- سيحلّ تلك المشكلة:
this.x = 9; // يشير المعامل this إلى الكائن العام
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX(); // 9
// ستستدعى الدالة في المجال العام
// إنشاء دالة جديدة مرتبطة بالكائن
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
توفير قائمة وسائط مبدئية
استخدامٌ بسيطٌ آخر للدالة bind
هو إنشاء دوال لها وسائط مُعرَّفة مسبقًا؛ فتلك الوسائط ستأتي بعد قيمة this
عند تعريف الدالة، وستُمرَّر إلى الدالة الهدف في أوّل قائمة الوسائط، وتتبعها الوسائط الأخرى التي تُحدَّد عند الاستدعاء:
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
// إنشاء دالة لها وسيطٌ يُمرَّر دومًا كأوّل وسيط ويليه الوسائط الأخرى
var leadingThirtysevenList = list.bind(null, 37);
var list2 = leadingThirtysevenList();
// [37]
var list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]
استخدامها مع الدالة setTimeout
عند استخدام الدالة window.setTimeout()
ستُضبَط الكلمة المحجوزة this
إلى الكائن العام window
، فعند التعامل مع الدوال التابعة لكائنات التي تتطلب أن تشير this
إلى الكائن، فيمكنك استخدام الدالة bind()
لربط this
إلى الدالة المستدعاة كما في المثال الآتي:
function LateBloomer() {
this.petalCount = Math.floor(Math.random() * 12) + 1;
}
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
إنشاء اختصارات
تفيد الدالة bind()
في الحالات التي نريد إنشاء اختصار إلى دالة التي تتطلب قيمة this
مُحدَّدة.
لنأخذ الدالة Array.prototype.slice
مثالًا، التي يمكنك استخدامها لتحويل كائن شبيه بالمصفوفات إلى مصفوفة حقيقة. يمكنك إنشاء اختصار كما يلي:
var slice = Array.prototype.slice;
// ...
slice.apply(arguments);
لكن مع استخدام الدالة bind()
نستطيع تبسيط ما سبق، ففي الشيفرة الآتية ترتبط slice
بالدالة Function.prototype.apply()
، وستُضبَط قيمة this
إلى الدالة Array.prototype.slice()
، وهذا يعني أنَّه لا حاجة إلى إضافة استدعاءات apply()
إضافية:
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.apply.bind(unboundSlice);
// ...
slice(arguments);
دعم المتصفحات
الميزة | Chrome | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
الدعم الأساسي | 7 | 4 | 9 | 11.6 | 5.1 |
مصادر ومواصفات
- مسودة المعيار ECMAScript Latest Draft.
- معيار ECMAScript 2015 (6th Edition).
- معيار ECMAScript 5.1.