مقدمة
في ECMASCRIPT ، هناك طريقتان أكثر شيوعًا لإنشاء كائنات وظيفية ، وهما باستخدام تعبيرات الوظائف أو استخدام إعلانات الوظيفة. في هذا الصدد ، توضح مواصفات ECMASCRIPT أن إعلانات الوظيفة يجب أن تحمل دائمًا معرفًا ، وهو ما نسميه اسم الوظيفة ، ويمكن حذف تعبيرات الوظائف. دعنا نلقي نظرة على المقدمة التفصيلية للاختلافات بين الاثنين.
ما هو إعلان الوظيفة؟
يمكن أن يحدد إعلان الوظيفة متغيرات الوظيفة المسماة دون تعيين قيم للمتغيرات. إعلان الوظيفة هو بنية مستقلة لا يمكن أن تتلاعب في الوحدات غير الوظيفية. يمكن مقارنتها بالإعلان المتغير. مثلما يجب أن يبدأ الإعلان المتغير بـ "var" ، يجب أن يبدأ إعلان الوظيفة بـ "وظيفة".
على سبيل المثال
شريط الدالة () {return 3 ؛}ECMA 5 (13.0) تعريف بناء الجملة:
function Identifier ( FormalParameterList[opt] ) { FunctionBody }
تتوفر أسماء الوظائف ضمن نطاقها الخاص ونطاق الوالدين (وإلا فلن تكون الوظيفة متاحة).
شريط الدالة () {return 3 ؛} bar () // 3bar // functionما هو تعبير الوظيفة؟
يعرّف تعبير الوظيفة وظيفة كجزء من عبارة تعبير (عادةً تخصيص متغير). يمكن تسمية الوظائف المحددة بواسطة تعبير الوظيفة أو مجهول. لا يمكن أن يبدأ تعبير الوظيفة بـ "وظيفة" (يجب أن تكون الأمثلة ذاتية التمثيل الذاتي التالية محاطة بأقواس).
على سبيل المثال
// مجهول الدالة expressionvar a = function () {return 3 ؛} // المسماة function expressionvar a = bar function () {return 3 ؛} // تعبير وظيفة استدعاء الذات (الدالة sealhello () {Alert ("hello!") ؛}) () ؛ECMA 5 (13.0) تعريف بناء الجملة:
function Identifieropt ( FormalParameterList[opt] ) { FunctionBody }
(هذا التعريف يشعر بعدم الإكمال لأنه يتجاهل شرطًا: البيان المحيطي هو تعبير ولا يبدأ بـ "وظيفة")
أسماء الوظائف (إن وجدت) غير متوفرة خارج نطاق (مقارنة بإعلان الوظيفة).
إذن ما هو بيان الوظيفة؟
بيان الوظيفة هو في بعض الأحيان طريقة أخرى لإعلان الوظيفة. لكن Kangax يشير إلى أنه في Mozilla ، عبارة الوظيفة هي امتداد لإعلان الوظيفة ، مما يسمح باستخدام بيان إعلان الوظيفة في أي مكان يسمح باستخدام البيانات. ومع ذلك ، فإن بيان الوظيفة ليس هو المعيار الآن ، لذلك لا ينصح باستخدامه في تطوير المنتج.
لنبدأ ببعض الاختبارات الصغيرة. خمن ما الذي سيظهر في المواقف التالية؟
السؤال 1:
دالة foo () {function bar () {return 3 ؛ } return bar () ؛ وظيفة الدالة () {return 8 ؛ }} Alert (foo ()) ؛السؤال 2:
دالة foo () {var bar = function () {return 3 ؛ } ؛ شريط العودة () ؛ var bar = function () {return 8 ؛ } ؛} Alert (foo ()) ؛السؤال 3:
ALERT (foo ()) ؛ function foo () {var bar = function () {return 3 ؛ } ؛ شريط العودة () ؛ var bar = function () {return 8 ؛ } ؛}السؤال 4:
وظيفة foo () {return bar () ؛ var bar = function () {return 3 ؛ } ؛ var bar = function () {return 8 ؛ } ؛} Alert (foo ()) ؛إذا لم تكن إجابتك 8 و 3 و 3 و [خطأ في النوع: الشريط ليس وظيفة] ، فاستمر في القراءة ... (حتى لو أجبت بشكل صحيح ، يجب عليك متابعة القراءة)
الآن دعنا نوضح الاختبار السابق.
السؤال 1 يستخدم إعلان الوظيفة ، مما يعني أنهم يتم رفعهم ...
انتظر ، ما هو الرفع؟
فيما يلي اقتباس من Ben Cherry: "عادةً ما يتم نقل إعلان الوظيفة ومتغير الوظيفة (" رفع ") إلى أعلى النطاق الحالي بواسطة مترجم JavaScript."
عند الترويج لإعلان الوظيفة ، سيتم الترويج لجسم الوظيفة بأكمله وفقًا لذلك ، وبالتالي فإن مدونة السؤال 1 تعمل مثل هذا بعد تفسيرها من قبل المترجم:
// ** تسلسل المعالجة المحاكاة للسؤال 1 ** وظيفة foo () {// تعريف الشريط بمجرد أن يكون شريط الوظائف () {return 3 ؛ } // redefine It function bar () {return 8 ؛ } // إرجاع شريط الإرجاع الخاص به () ؛ // 8} ALERT (FOO ()) ؛ومع ذلك ، غالبًا ما يتم إخبارنا بأن الكود وراء بيان الإرجاع لا يمكن تشغيله ...
أثناء تنفيذ JavaScript ، هناك مفهومين: السياق (ECMA 5 تقسمه إلى البيئة المعجمية ، وبيئة المتغير والتجند) والعملية (سلسلة من العبارات التي تسمى بالتسلسل). عندما يدخل البرنامج مجال التنفيذ ، يسبب الإعلان بيئة متغيرة. فهي مختلفة عن البيان (مثل الإرجاع) ولا تتبع قواعد تشغيل البيان.
هل سيتم تعزيز تعبير الوظيفة؟
ذلك يعتمد على التعبير. على سبيل المثال ، التعبير الأول في السؤال 2:
var bar = function () {return 3 ؛} ؛(VAR BAR) على يسار العلامة المتساوية هو إعلان متغير. سيتم الترويج للإعلان المتغير ، لكن التعبير عن المهمة لن. لذلك عند الترويج للشريط ، سيتم تهيئة المترجم المترجم مثل هذا: VAR BAR = غير محدد. لن يتم تعزيز تعريف الوظيفة نفسها.
(يتم تعيين متغيرات ECMA 5 12.2 مع initialzier بواسطة التعيين عند تنفيذ variablestatement ، وليس عند إنشاء المتغير.)
لذلك ، سيتم تشغيل رمز السؤال 2 بالترتيب التالي:
// ** تسلسل المعالجة المحاكاة للسؤال 2 ** وظيفة foo () {// إعلان لكل تعبير دالة var bar = غير محدد ؛ var bar = غير محدد ؛ // يتم تنفيذ التعبير الوظيفي الأول = function () {return 3 ؛ } ؛ // الوظيفة التي تم إنشاؤها بواسطة تعبير الوظيفة الأولى يتم استدعاء شريط الإرجاع () ؛ // تعبير الوظيفة الثانية غير قابلة للوصول} التنبيه (foo ()) ؛ // 3قد تقول أنه يمكن شرح ذلك ، لكن الإجابة على السؤال 3 خاطئة. سأبلغ عن خطأ عند تشغيل Firebug.
احفظ الرمز في ملف HTML وحاول تشغيله على Firefox. أو تشغيل في IE8 أو Chrome أو Safari Console. من الواضح أن وحدة التحكم في Firebug لن تعزز الوظيفة عند تشغيل الكود في النطاق "العالمي" (في الواقع ليس عالميًا ، ولكن النطاق "Firebug" الفريد - فقط حاول تشغيل "هذا == النافذة" في وحدة التحكم في Firebug).
السؤال 3 والسؤال 1 لهما منطق مماثل. هذه المرة تم الترويج لوظيفة FOO.
السؤال 4 بسيط للغاية ، لا يوجد أي تحسين على الإطلاق ...
يمكن القول ذلك ، ولكن إذا لم يكن هناك تحسن على الإطلاق ، فسيكون "شريط غير محدد" بدلاً من "الشريط وليس وظيفة". لا يوجد في الواقع أي تحسين وظيفي في هذا المثال ، ولكن هناك تحسن متغير. لذلك ، يتم الإعلان عن الشريط في البداية ، ولكن لا يتم تعريف قيمته. يتم تنفيذ الرموز الأخرى بالترتيب.
// ** تسلسل المعالجة المحاكاة للسؤال 4 ** وظيفة foo () {// إعلان لكل تعبير دالة var bar = undefined ؛ var bar = غير محدد ؛ شريط العودة () ؛ // typeerror: "شريط غير محدد" // لا يتم الوصول إلى تعبير الوظيفة} التنبيه (foo ()) ؛ماذا يجب أن تهتم به؟
يحظر المسؤول استخدام إعلان الوظيفة في الوحدات غير الوظيفية (مثل IF). ومع ذلك ، فإن جميع المتصفحات تدعمها ، لكن تفسيراتها مختلفة.
على سبيل المثال ، سوف يرمي مقتطف الكود التالي خطأً في Firefox 3.6 لأنه يفسر إعلان الوظيفة كبيان وظيفة (انظر أعلاه) ، لذلك لم يتم تعريف x. ولكن في IE8 و Chrome 5 و Safari 5 ، سيتم إرجاع الوظيفة X (مثل إعلان الوظيفة القياسية).
دالة foo () {if (false) {function x () {} ؛ } return x ؛} ALERT (foo ()) ؛يمكن ملاحظة أن استخدام إعلان الوظيفة قد يسبب الارتباك ، فهل له أي مزايا؟
قد تقول إن إعلان الوظيفة فضفاض تمامًا - إذا حاولت استخدام وظيفة قبل الإعلان ، يمكن للترقية بالفعل تصحيح الطلب بحيث يمكن استدعاء الوظيفة بشكل صحيح. لكن هذا النوع من الرخاوة لا يفضي إلى الترميز الصارم ، ومن منظور طويل الأجل ، من المحتمل أن يعزز الحوادث بدلاً من منعها. بعد كل شيء ، هناك سبب يرتب المبرمجون البيانات بترتيب محدد.
هل هناك أي أسباب أخرى لدعم تعبير الوظيفة؟
ماذا تعتقد؟
1) يشعر إعلان الوظيفة بأنه هو تقليد إعلانات طريقة على غرار Java ، لكن طرق Java ليست هي نفسها JavaScript. في JavaScript ، الوظائف هي كائنات حية ذات قيم. طرق Java هي فقط تخزين البيانات الوصفية. تحدد القطعان التاليتان من الكود الوظيفة ، لكن تعبير الوظيفة فقط يبدو وكأنه كائن.
// دالة إعلان FunctionFunction Add (a ، b) {return a + b} ؛ // function expressionvar add = function (a ، b) {return a + b} ؛2) تعبير الوظيفة له المزيد من الاستخدامات. يمكن أن يوجد إعلان الوظيفة فقط في الأيتام كـ "بيان". كل ما يمكن أن تفعله هو إنشاء متغير كائن ضمن النطاق الحالي. تعبير الوظيفة ، بحكم التعريف ، هو جزء من بنية كبيرة. إذا كنت ترغب في إنشاء وظائف مجهولة ، أضف وظائف إلى نماذج أولية ، أو استخدام الوظائف كخاصية للكائنات الأخرى ، يمكنك استخدام تعبير الوظيفة. عندما تستخدم التطبيقات المتقدمة ، مثل الكاري أو التأليف ، يمكنك استخدام تعبير الوظيفة عند إنشاء وظائف جديدة. تعبير الوظيفة والبرمجة الوظيفية لا ينفصلان.
// function expressionvar sealhhello = Alert.curry ("Hello!") ؛هل هناك أي عيوب في تعبير الوظيفة؟
تعبير الوظيفة يخلق معظم الوظائف مجهولة. على سبيل المثال ، الوظيفة التالية مجهولة ، اليوم هو مجرد إشارة إلى وظيفة مجهولة:
var today = function () {return new date ()}هل سيكون هذا مشكلة؟ ليس في معظم الحالات ، ولكن كما أشار نيك فيتزجيرالد ، يمكن أن يكون تصحيح وظائف مجهولة الهوية مزعجة. ويوصي باستخدام تعبيرات الوظائف المسماة (NFES) كمساحة عمل:
var today = function today () {return new date ()}ومع ذلك ، كما قال Asen Bozhilov (ووثائق Kangax) لا يمكن تنفيذ NFEs بشكل صحيح أقل من IE9.
ختاماً
إن إعلان الوظيفة الموضوعة عشوائيًا هو مضللة ونادراً ما لا يمكن أن يحل إعلان الوظيفة (إن وجدت) ، وتخصيص القيم للمتغيرات مع تعبير الوظيفة. ولكن إذا كان إعلان الوظيفة مطلوبًا ، فإن وضعه في الجزء العلوي من النطاق يمكن أن يقلل من الارتباك. لا تضع إعلان الوظيفة في بيان if.
بعد قوله كثيرًا ، قد يكون إعلان الوظيفة مفيدًا في وضعك. لا شئ. الدور عقيدة خطرة وغالبًا ما تتسبب في التغلب على الكود حول الأدغال. والأهم من ذلك ، أنك تفهم المفهوم حتى تتمكن من تحديد الطريقة التي يجب إنشاء الوظيفة بناءً على الموقف الخاص بك. ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون هذا المقال مفيدًا للجميع في هذا الصدد.