البرمجة المعيارية هي نمط برمجة JavaScript شائع جدًا. يمكن أن يجعل الفهم رمزًا بشكل عام ، ولكن هناك العديد من الممارسات الممتازة التي ليست معروفة جيدًا.
قاعدة
دعنا أولاً نوضح باختصار بعض الأنماط المعيارية منذ نشر إريك ميراجليا (مطور YUI) لأول مرة مدونة قبل ثلاث سنوات تصف الأنماط المعيارية. إذا كنت بالفعل على دراية بهذه الأنماط المعيارية ، فيمكنك تخطي هذا القسم مباشرة والبدء في القراءة من "الوضع المتقدم".
إغلاق مجهول
هذا هيكل أساسي يجعل كل شيء ممكنًا ، وهو أيضًا أفضل ميزة لـ JavaScript. سنقوم ببساطة بإنشاء وظيفة مجهولة وتنفيذها على الفور. سيتم تشغيل جميع التعليمات البرمجية ضمن هذه الوظيفة وتعيش في إغلاق يوفر الخصخصة ، وهو ما يكفي لتمكين المتغيرات في هذه الإغلاق لتشغيل طوال حياة تطبيقنا.
نسخة الكود كما يلي:
(وظيفة () {
// ... جميع الجامعات والوظائف موجودة في هذا النطاق فقط
// لا يزال يحافظ على الوصول إلى جميع الكرات
} ()) ؛
لاحظ الأقواس الخارجية لهذا الزوج لف وظائف مجهولة المصدر. بسبب خصائص اللغة لجافا سكريبت ، هذا ضروري للأقواس. تعتبر البيانات التي تبدأ بوظيفة الكلمة الرئيسية في JS دائمًا تعريفيًا. لف هذا الرمز بين قوسين لإعلام المترجم المترجم أن هذا تعبير دالة.
استيراد متغير عالمي
لدى JavaScript ميزة تسمى المتغيرات العالمية الضمنية. بغض النظر عن مكان استخدام اسم متغير ، سيجد المترجم المترجم بيان إعلان VAR للمتغير في الاتجاه المعاكس وفقًا لسلسلة النطاق. إذا لم يتم العثور على بيان إعلان VAR ، فسيتم اعتبار هذا المتغير متغيرًا عالميًا. إذا تم استخدام هذا المتغير في عبارة تعيين ولم يكن متغيرًا غير موجود ، فسيتم إنشاء متغير عالمي. هذا يعني أنه من السهل استخدام أو إنشاء متغيرات عالمية في عمليات إغلاق مجهولة. لسوء الحظ ، هذا يجعل الكود مكتوبًا للغاية من الصعب للغاية الحفاظ عليه ، لأنه بالنسبة لمشاعر الناس البديهية ، من المستحيل معرفة لمحة عن أن هذه المتغيرات عالمية.
لحسن الحظ ، فإن وظائفنا المجهولة توفر حلولًا بسيطة. ما عليك سوى تمرير المتغير العالمي كمعلمة في وظيفتنا المجهولة ، يمكنك الحصول على رمز أوضح وأسرع من المتغير العالمي الضمني. هنا مثال:
نسخة الكود كما يلي:
(وظيفة ($ ، yahoo) {
// الآن يمكنك الوصول إلى Globals JQuery (AS $) و Yahoo في هذا الرمز
} (jquery ، yahoo)) ؛
تصدير الوحدة النمطية
في بعض الأحيان لا تريد فقط استخدام المتغيرات العالمية ، بل تريد أيضًا إعلانها للاستخدام المتكرر. يمكننا القيام بذلك بسهولة عن طريق اشتقاقها - من خلال قيمة إرجاع الوظائف المجهولة. سيؤدي القيام بذلك إلى إكمال نموذج معياري أساسي ، وسيكون ما يلي مثالًا كاملاً:
نسخة الكود كما يلي:
وحدة var = (function () {
var my = {} ،
PrivateVariable = 1 ؛
وظيفة privatemethod () {
// ...
}
my.moduleProperty = 1 ؛
my.modulemethod = function () {
// ...
} ؛
أعد بلدي ؛
} ()) ؛
لاحظ أننا أعلنا وحدة عالمية تسمى الوحدة ، والتي لها خصائص عامة: طريقة تسمى module.modulemethod ومتغير يسمى module.moduleproperty. بالإضافة إلى ذلك ، فإنه يحافظ على حالة مدمجة خاصة تستخدم إغلاق الوظائف المجهولة. في الوقت نفسه ، يمكننا بسهولة استيراد المتغيرات العالمية المطلوبة واستخدام هذا النمط المعياري الذي تعلمناه من قبل.
الوضع المتقدم
الأساس الموضح في القسم أعلاه يكفي للتعامل مع العديد من المواقف ، والآن يمكننا تطوير هذا النموذج المعياري لإنشاء هياكل أكثر قوة وقابلة للتطوير. لنبدأ بوحدة الوحدة النمطية ونقدم هذه الأوضاع المتقدمة واحدة تلو الأخرى.
وضع التكبير
يجب أن تكون الوحدة بأكملها قيودًا على الوضع المعياري في ملف واحد. أي شخص يشارك في مشروع كبير سوف يفهم قيمة تقسيم الملفات المتعددة باستخدام JS. لحسن الحظ ، لدينا تطبيق رائع لتضخيم الوحدات. أولاً ، نستورد وحدة نمطية ، نضيف خصائص إليها ، ونقوم أخيرًا بتصديرها. فيما يلي مثال - تكبير من الوحدة الأصلية:
نسخة الكود كما يلي:
وحدة var = (الدالة (my) {
my.anothermethod = function () {
// طريقة إضافة ...
} ؛
أعد بلدي ؛
} (وحدة)) ؛
نستخدم الكلمة الرئيسية VAR لضمان الاتساق ، على الرغم من أنها ليست ضرورية هنا. بعد تنفيذ هذا الرمز ، تحتوي الوحدة النمطية لدينا بالفعل على طريقة عامة جديدة تسمى Module.anothermethod. سيحافظ هذا الملف المكبر أيضًا على حالته المدمجة الخاصة والكائنات المستوردة.
وضع التكبير الواسع
يتطلب مثالنا أعلاه تنفيذ وحدة التهيئة الخاصة بنا أولاً ثم يتم تنفيذ الوحدة النمطية المتضخمة ، وبالطبع قد لا يكون ذلك ضروريًا في بعض الأحيان. واحدة من أفضل الأشياء التي يمكن لتطبيقات JavaScript القيام بها لتحسين الأداء هو تنفيذ البرامج النصية بشكل غير متزامن. يمكننا إنشاء وحدات متعددة المرونة وتمكينها من تحميلها بأي ترتيب من خلال وضع التكبير الواسع. يجب تنظيم كل ملف في الهيكل التالي:
نسخة الكود كما يلي:
وحدة var = (الدالة (my) {
// إضافة قدرات ...
أعد بلدي ؛
} (الوحدة النمطية || {})) ؛
في هذا النمط ، فإن تعبير VAR يجعله ضروريًا. لاحظ أنه إذا لم يتم تهيئة الوحدة النمطية ، فسيقوم عبارة الاستيراد بإنشاء وحدة نمطية. هذا يعني أنه يمكنك استخدام أداة مثل LABJS لتحميل جميع ملفات الوحدة النمطية بالتوازي دون حظرها.
وضع التوسيع الضيق
وضع العدوى العريض جيد جدًا ، لكنه سيضع أيضًا بعض القيود على الوحدة النمطية الخاصة بك. الأهم من ذلك ، لا يمكنك الكتابة فوق خصائص الوحدة النمطية بأمان. لا يمكنك استخدام الخصائص من الملفات الأخرى عند التهيئة (ولكن يمكنك استخدامها عند التشغيل). يحتوي وضع التوسيع الضيق على تسلسل محمّل ويسمح بخصائص تجاوز. فيما يلي مثال بسيط (تكبير في الوحدات النمطية الأصلية):
نسخة الكود كما يلي:
وحدة var = (الدالة (my) {
var old_modulemethod = my.modulemethod ؛
my.modulemethod = function () {
// Override ، يمكنه الوصول إلى القديم من خلال Old_ModuleMethod ...
} ؛
أعد بلدي ؛
} (وحدة)) ؛
نقوم بتجاوز تنفيذ الوحدة النمطية. modulemethod في المثال أعلاه ، ولكن عند الحاجة ، يمكننا الحفاظ على إشارة إلى الطريقة الأصلية.
استنساخ والميراث
نسخة الكود كما يلي:
var module_two = (function (old) {
var my = {} ،
مفتاح؛
لـ (المفتاح في القديم) {
if (old.hasownproperty (مفتاح)) {
بلدي [المفتاح] = القديم [المفتاح] ؛
}
}
var super_modulemethod = old.modulemethod ؛
my.modulemethod = function () {
// طريقة التجاوز على الاستنساخ ، والوصول إلى Super من خلال super_modulemethod
} ؛
أعد بلدي ؛
} (وحدة)) ؛
ربما يكون هذا النموذج هو الخيار الأكثر مرونة. إنه يجعل الرمز يبدو أنيقًا ، لكن ذلك يأتي على حساب المرونة. كما كتبت أعلاه ، إذا كانت الخاصية كائنًا أو وظيفة ، فلن يتم نسخها ، ولكنها ستصبح المرجع الثاني للكائن أو الوظيفة. إذا قمت بتعديل أحدهم ، فستقوم بتعديل الآخر في نفس الوقت (ملاحظة المترجم: لأنها ببساطة واحدة!). يمكن حل ذلك عن طريق عملية الاستنساخ العودية ، ولكن قد لا يتم حل استنساخ الوظيفة ، وربما يمكن حلها باستخدام eval. لذلك ، أخبر هذه الطريقة في هذه المقالة فقط لا تأخذ في الاعتبار سلامة المقالة.
متغيرات خاصة بالملف
هناك قيود كبيرة على تقسيم وحدة نمطية إلى ملفات متعددة: يحافظ كل ملف على متغيراته الخاصة ولا يمكنه الوصول إلى المتغيرات الخاصة للملفات الأخرى. ولكن يمكن حل هذه المشكلة. فيما يلي مثال على وحدة واسعة النطاق التي تحافظ على متغيرات خاصة عبر الملفات:
نسخة الكود كما يلي:
وحدة var = (الدالة (my) {
var _private = my._private = my._private || {} ،
_seal = my._seal = my._seal || وظيفة () {
حذف my._private ؛
حذف my._seal ؛
حذف my._unseal ؛
} ،
_unseal = my._unseal = my._unseal || وظيفة () {
my._private = _private ؛
my._seal = _seal ؛
my._unseal = _unseal ؛
} ؛
// وصول دائم إلى _private ، _seal ، و _unseal
أعد بلدي ؛
} (الوحدة النمطية || {})) ؛
يمكن لجميع الملفات تعيين خصائص على متغيراتها _PRICING ، وتفهم أنه يمكن الوصول إليها بواسطة ملفات أخرى. بمجرد تحميل هذه الوحدة ، يمكن للتطبيق استدعاء الوحدة النمطية. إذا كانت هذه الوحدة بحاجة إلى إعادة تعطيل ، فيمكن أن تتصل الطريقة الداخلية في أي ملف _unseal () قبل تحميل الملف الجديد ، واتصل _seal () مرة أخرى بعد تنفيذ الملف الجديد. أستخدم هذا النمط في العمل الآن ولم أره في أي مكان آخر. أعتقد أن هذا نموذج مفيد للغاية ويستحق كتابة مقال عن هذا النموذج نفسه.
النسيجية الفرعية
من الواضح أن وضعنا المتقدم الأخير هو الأسهل. هناك العديد من الأمثلة الممتازة لإنشاء علامات فرعية. إنه مثل إنشاء وحدة عادية:
نسخة الكود كما يلي:
module.sub = (function () {
var my = {} ؛
// ...
أعد بلدي ؛
} ()) ؛
على الرغم من أن هذا يبدو بسيطًا ، أعتقد أنه من الجدير بالذكر هنا. تحتوي العارض الفرعي على جميع المزايا المتقدمة للوحدات العامة ، بما في ذلك وضع التضخيم وحالة الخصخصة.
ختاماً
يمكن دمج معظم الأوضاع المتقدمة لإنشاء وضع أكثر فائدة. إذا كنت أرغب حقًا في التوصية بنمط معياري لتصميم التطبيقات المعقدة ، فسوف أختار الجمع بين وضع التضخيم الواسع والمتغيرات الخاصة والمواد الفرعية.
لم أفكر في أداء هذه الأوضاع ، لكنني أفضل تحويل هذا إلى طريقة أبسط للتفكير: إذا كان الوضع المعياري له أداء جيد ، فيمكنه القيام بعمل رائع في تقليله ، مما يجعل تنزيل ملف البرنامج النصي هذا بشكل أسرع. يتيح استخدام وضع التوسيع الواسع تنزيلات موازية بسيطة غير حظر ، والتي تزيد من التنزيلات. قد يكون وقت التهيئة أبطأ قليلاً من الأساليب الأخرى ، ولكنه يستحق ذلك بعد وزن إيجابيات وسلبيات. طالما كان الاستيراد المتغير العالمي دقيقًا ، يجب أن يتأثر أداء وقت التشغيل ، ومن الممكن أيضًا تحقيق سرعات تشغيل أسرع في العارض الفرعي عن طريق تقصير السلسلة المرجعية مع المتغيرات الخاصة.
كخلاصة ، فيما يلي مثال على تحميل وحدة الطفل ديناميكيًا في الوحدة الأم (إنشاءه إذا لم تكن الوحدة الأصل موجودة). من أجل البساطة ، قمت بإزالة المتغيرات الخاصة ، وبالطبع يكون من السهل جدًا إضافة متغيرات خاصة. يسمح نمط البرمجة هذا بقاعدة رمز الهيكل الهرمي المعقدة بالكامل لتتوازى من خلال العلامات الفرعية.
نسخة الكود كما يلي:
var util = (function (parent ، $) {
var my = parent.ajax = parent.ajax || {} ؛
my.get = function (url ، params ، callback) {
// حسنًا ، لذلك أنا أغش قليلاً :)
إرجاع $ .getjson (url ، params ، رد الاتصال) ؛
} ؛
// إلخ...
إرجاع الوالد ؛
} (util || {} ، jQuery)) ؛
تلخص هذه المقالة أفضل الممارسات الحالية لـ "JavaScript Modular Programming" وتشرح كيفية وضعها موضع التنفيذ. على الرغم من أن هذا ليس برنامجًا تعليميًا أساسيًا ، إلا أنه يمكنك فهمه من خلال فهم صغير للجملة الأساسية لـ JavaScript.