ماذا يحدث عندما يتم استيراد وحدة JS مرتين؟

لنبدأ هذه المقالة بسؤال. incrementتحتوي وحدة ES2015 على الكود التالي:

// increment.js
let counter = 0;
counter++;

export default counter;

في وحدة أخرى ، والتي سوف نسميها consumer، يتم استيراد الوحدة المذكورة أعلاه مرتين:

// consumer.js
import counter1 from './increment';
import counter2 from './increment';

counter1; // => ???
counter2; // => ???

والآن ، في الواقع ، سؤال. ما يحصل في المتغيرات counter1و counter2بعد الوحدة consumer؟ للإجابة على هذا السؤال ، تحتاج إلى فهم كيفية تنفيذ JavaScript للوحدات وكيف يتم استيرادها.





تنفيذ الوحدة


من أجل فهم كيفية عمل آليات JavaScript الداخلية ، من المفيد النظر في المواصفات .

وفقًا للمواصفات ، ترتبط كل وحدة JavaScript بوحدة سجل الوحدة . يحتوي هذا الإدخال على طريقة Evaluate()تنفيذ الوحدة النمطية:

إذا تم تنفيذ هذه الوحدة بنجاح بالفعل ، قم بإرجاع غير معرّف ؛ [...]. خلاف ذلك ، تنفيذ جميع تبعيات هذه الوحدة بشكل عابر ثم تنفيذ هذه الوحدة.
ونتيجة لذلك ، اتضح أن نفس الوحدة يتم تنفيذها مرة واحدة فقط.

للأسف ، ما تحتاج إلى معرفته للإجابة على سؤالنا لا يقتصر على ذلك. كيفية التأكد من استدعاء التعليماتimport باستخدام نفس المسارات سيعود نفس الوحدة النمطية؟

السماح بأوامر الاستيراد


العملية المجردة HostResolveImportedModule () هي المسؤولة عن ربط المسار إلى الوحدة (المحدد) بوحدة نمطية معينة . يبدو رمز استيراد الوحدة النمطية كما يلي:

import module from 'path';

إليك ما تقوله المواصفات عن ذلك:

يجب أن يستوفي تنفيذ HostResolveImportedModule المتطلبات التالية:

  • يجب أن تكون القيمة المرجعة العادية مثيلًا لفئة فرعية معينة من سجل الوحدة.
  • إذا كان كيان سجل الوحدة المتوافق مع الزوج المرجعي سكريبتورمودول ، المحدد غير موجود ، أو لا يمكن إنشاء مثل هذا الكيان ، يجب طرح استثناء.
  • في كل مرة يتم استدعاء هذه العملية بالتمرير إليها كوسيطة زوج معين من المراجع سكريبتورمودولي ، محدد ، يجب ، في حالة تنفيذها المعتاد ، إرجاع نفس مثيل كيان سجل الوحدة.

الآن فكر في هذا بطريقة مفهومة أكثر.

HostResolveImportedModule(referencingScriptOrModule, specifier)- عملية مجردة تُرجع الوحدة المقابلة لزوج من المعلمات referencingScriptOrModule، specifier:

  • المعلمة referencingScriptOrModuleهي الوحدة النمطية الحالية ، أي الوحدة التي تستورد.
  • المعلمة specifierهي سلسلة تطابق مسار الوحدة النمطية في التعليمات import.

في نهاية الوصف ، HostResolveImportedModule()يقال أنه عند استيراد الوحدات التي تتوافق مع نفس المسار ، يتم استيراد نفس الوحدة:

import moduleA from 'path';
import moduleB from 'path';
import moduleC from 'path';

// moduleA, moduleB  moduleC -    

moduleA === moduleB; // => true
moduleB === moduleC; // => true

ومن المثير للاهتمام ، أن المواصفات تشير إلى أن المضيف (المتصفح ، بيئة Node.js ، بشكل عام - أي شيء يحاول تنفيذ تعليمات JavaScript البرمجية) يجب أن يوفر تنفيذًا محددًا HostResolveImportedModule().

إجابة


بعد قراءة متعمقة للمواصفات ، يصبح من الواضح أن وحدات JavaScript يتم تنفيذها مرة واحدة فقط أثناء الاستيراد. وعند استيراد وحدة نمطية باستخدام نفس المسار ، يتم إرجاع نفس مثيل الوحدة النمطية.

دعنا نعود إلى سؤالنا.

يتم incrementتنفيذ الوحدة دائمًا مرة واحدة فقط:

// increment.js
let counter = 0;
counter++;

export default counter;

بغض النظر عن عدد المرات التي تم فيها استيراد الوحدة النمطية increment، يتم counter++تقييم التعبير مرة واحدة فقط. متغير counterتم تصديره باستخدام آلية التصدير الافتراضية 1.

الآن نلقي نظرة على الوحدة consumer:

// consumer.js
import counter1 from './increment';
import counter2 from './increment';

counter1; // => 1
counter2; // => 1

الأوامر import counter1 from './increment'و import counter2 from './increment'استخدام نفس المسار - './increment'. ونتيجة لذلك ، اتضح أنه تم استيراد نفس مثيل الوحدة.

وتبين أن نفس القيمة 1 و كتب لمتغيرات counter1و counter2ل consumer.

ملخص


بعد فحص سؤال بسيط ، تمكنا من معرفة المزيد حول كيفية تنفيذ واستيراد وحدات JavaScript.

القواعد المستخدمة عند استيراد الوحدات بسيطة للغاية: يتم تنفيذ نفس الوحدة مرة واحدة فقط. وبعبارة أخرى ، يتم تنفيذ ما هو في نطاق مستوى الوحدة النمطية مرة واحدة فقط. إذا تم استيراد وحدة تم تنفيذها بالفعل مرة واحدة مرة أخرى ، فلن يتم تنفيذها مرة أخرى. عند استيراد وحدة نمطية ، يستخدم ما تم الحصول عليه نتيجة جلسة سابقة لمعرفة ما يتم تصديره بالضبط.

إذا تم استيراد وحدة نمطية عدة مرات ، ولكن محدد الوحدة النمطية (المسار إليها) لا يزال كما هو ، فإن مواصفات JavaScript تضمن استيراد نفس مثيل الوحدة.

القراء الأعزاء! كم مرة تلجأ إلى قراءة مواصفات جافا سكريبت ، واكتشاف ميزات أداء تركيبات لغة معينة؟


All Articles