عند الحكم على نوع الوظيفة، نستخدم عادة طريقة typeof في الظروف العادية، وسوف تحصل على التأثير الذي توقعناه. لكن هناك بعض التفاصيل التي لا نعرفها جيدًا. وبعد تحليل هذه التفاصيل، قدم لنا جون ريسيج الحل الأمثل، والذي سيتم عرضه بالتفصيل في هذا المقال:
1. تفاصيل غير معروفة عن الطرق التقليدية
ولا شك أنه عند تحديد نوع الوظيفة نستخدم طريقة typeof مثل:
وظيفة الجبهة الوطنية () {
//محتوى
}
تنبيه (نوع fn) // النتيجة هي "وظيفة".
ومع ذلك، لا تعمل هذه الطريقة كما هو متوقع في بعض المتصفحات.
1. Firefox2 وFirefox3
في هذين المستعرضين، يؤدي استخدام typeof لاكتشاف نوع عنصر كائن HTML إلى نتيجة "دالة" غير دقيقة بدلاً من "كائن"، مثل HTMLDocument. يحب:
تنبيه (نوع HTMLDocument)؛
// في Firefox2 النتيجة هي "وظيفة"؛
// في Firefox3 النتيجة هي "كائن"؛
2.فايرفوكس2
بالنسبة للتعبيرات العادية، النتيجة التي يتم إرجاعها في هذا المتصفح هي "function" (النتيجة هي "object" في Firefox3)، مثل:
فار ريج = /اختبار/;
تنبيه (نوع ريج) ؛
// في Firefox2 النتيجة هي "وظيفة"؛
// في Firefox3 النتيجة هي "كائن"؛
ملاحظة: لقد اختبرت ذلك في Safari، وكانت النتيجة أيضًا "وظيفة".
3.IE6 وIE7
عند استخدام طريقة typeof على عنصر DOM في IE، تكون النتيجة "object". يحب:
تنبيه (نوع الوثيقة.getElementsByTagName("body")[0].getAttribute);
// النتيجة هي "كائن"
4. سفاري 3
يعتقد Safari أن قائمة NodeList لعناصر DOM هي وظيفة، مثل:
تنبيه(نوع الوثيقة.body.childNodes);
// النتيجة هي "وظيفة"
من الواضح، إذا كنت تريد اختبار ما إذا كان الكائن عبارة عن وظيفة، فإن استخدام طريقة typeof لا يضمن نتيجة الاختبار بالمعنى الحقيقي. إذن، نحن بحاجة إلى حل يضمن نتائج الاختبار في جميع المتصفحات. نحن نعلم أن الوظيفة نفسها لها طريقتان، application() و call()، ولكن هاتين الطريقتين غير موجودتين في الوظيفة الإشكالية في IE.
تنبيه (نوع الوثيقة.getElementsByTagName("body")[0].getAttribute.call)
// النتيجة "غير محددة" في IE
ومن الواضح أننا لا نستطيع الاستفادة من هاتين الطريقتين.
2. الحل الأمثل وعملية التنفيذ
قدم لنا جون ريسيج حلاً مثاليًا لهذه الطريقة المعقدة ولكن الثابتة لتحديد ما إذا كان الكائن عبارة عن دالة أم لا، وهي كما يلي:
الدالة هي الوظيفة (الجبهة الوطنية) {
return !!fn && !fn.nodeName && fn.constructor != String &&
fn.constructor != RegExp && fn.constructor != الصفيف &&
/function/i.test( fn + "" );
}
تتأكد هذه الوظيفة أولاً من وجود كائن الاختبار وتقوم بتسلسله في سلسلة تحتوي على "وظيفة". وهذا هو أساس اكتشافنا (fn.constructor != String، fn.constructor != Array، و fn.constructor != RegExp ) . بالإضافة إلى ذلك، نحتاج إلى التأكد من أن الوظيفة المعلنة ليست عقدة DOM (fn.nodeName). وبعد ذلك، يمكننا إجراء اختبار toString. إذا قمنا بتحويل دالة إلى سلسلة، في المتصفح (fn+"") يعطينا النتيجة مثل "اسم الوظيفة (){...}". الآن، تحديد ما إذا كانت دالة هو أمر بسيط مثل التحقق مما إذا كانت السلسلة تحتوي على كلمة "function". وهذا يعمل بشكل رائع، بالنسبة لأي وظيفة معنية، نحصل على النتائج التي نحتاجها في جميع المتصفحات. بالمقارنة مع الطريقة التقليدية، فإن سرعة تشغيل هذه الوظيفة غير مرضية إلى حد ما ويوصي المؤلف باستخدامها بشكل متحفظ.
John Resig هو مطور مكتبة jQuery، وأعتقد أن الأصدقاء الذين يستخدمون هذه المكتبة على دراية بتركيبها المختصر وأدائها الممتاز. بالإضافة إلى السعي وراء بساطة التعليمات البرمجية والأداء العالي، فإن روح الكمال التي يتمتع بها المؤلف مثيرة للإعجاب أيضًا. إذا كنت تسعى إلى الكمال، أعتقد أن هذه المقالة ستكون مفيدة لك.
النص الأصلي: http://www.denisdeng.com/?p=426