فهم مواصفات ECMAScript ، الجزء 1



يوم جيد يا اصدقاء!

في هذه المقالة ، نأخذ وظيفة من المواصفات ونحلل تفسيرها. اذهب.

مقدمة


حتى إذا كنت تعرف جافا سكريبت جيدًا ، فقد تكون قراءة المواصفات صعبة. يوضح الكود التالي استخدام Object.prototype.hasOwnProperty:

const o = {
    foo: 1
}
o.hasOwnProperty('foo') // true
o.hasOwnProperty('bar') // false

في المثال ، لا يحتوي الكائن "o" على طريقة "hasOwnProperty" ، لذا فإننا نشير إلى النموذج الأولي الخاص به - "Object.prototype" (سلسلة النموذج الأولي).

لوصف كيفية عمل Object.hasOwnProperty ، تستخدم المواصفات الرمز الزائف التالي:

Object.prototype.hasOwnProperty (V)

عندما يتم استدعاء hasOwnProperty مع الوسيطة V ، يتم تنفيذ الخطوات التالية: ... و HasOwnProperty (O، P) يتم استخدام العملية التجريدية HasOwnProperty لتحديد ما إذا كان للكائن خاصية خاصة به مع مفتاح معين. يتم إرجاع القيمة المنطقية. يتم استدعاء العملية باستخدام وسيطات O و P. تتكون هذه العملية من الخطوات التالية: ما هي "العملية المجردة"؟ ماذا [[ ]]؟ لماذا تحتوي الدالة على علامة استفهام؟ ماذا يعني "التأكيد"؟ هيا نكتشف.

  1. P ? ToPropertyKey(V)
  2. O ? ToObject( this)
  3. ? HasOwnProperty(O, P).







  1. (assert): Type(O) Object.
  2. : IsPropertyKey(P) true.
  3. desc ? O.[[GetOwnProperty]](P).
  4. desc undefined, false.
  5. true.





أنواع اللغة وأنواع المواصفات


لنبدأ بشيء مألوف. في المواصفات ، هناك قيم مثل غير محددة وصحيحة وخاطئة ، وهي معروفة لنا من قبل JS. كلهم "قيم اللغة" ، "قيم أنواع اللغة" ، والتي يتم تعريفها أيضًا بواسطة المواصفات.

تستخدم المواصفات قيم اللغة المضمنة ، على سبيل المثال ، قد يحتوي نوع بيانات داخلي على حقل بقيمة صواب أو خطأ. لا تستخدم محركات JS بشكل عام المعاني اللغوية في آلياتها الداخلية. على سبيل المثال ، إذا كان محرك JS مكتوبًا بلغة C ++ ، فمن المرجح أن يستخدم الصواب والخطأ من C ++ ، بدلاً من التمثيل الداخلي للقيم المنطقية من JS.

بالإضافة إلى أنواع اللغات ، تستخدم المواصفات أنواعًا خاصة (أنواع المواصفات) - الأنواع المستخدمة فقط في المواصفات. محركات JS ليست مطلوبة لتنفيذها (لكنها تستطيع). في هذه المقالة سوف نتعرف على النوع الخاص "سجل" (سجل) ونوعه الفرعي "سجل الإنجاز" (سجل الإنجاز).

عمليات الملخص


العمليات المجردة هي وظائف محددة في المواصفات ؛ يتم تعريفها من أجل تقليل المواصفات. محركات JS ليست مطلوبة لأداء وظائف منفصلة. في JS ، لا يمكن استدعاؤهم مباشرة.

فتحات داخلية وطرق داخلية


يشار إلى الفتحات الداخلية والأساليب الداخلية بأسماء مضمنة في [[]].

الفتحات الداخلية هي عناصر (مجموعات) بيانات لكائن JS أو نوع خاص. يتم استخدامها لتخزين معلومات حول حالة الكائن. الطرق الداخلية هي وظائف أعضاء لكائن JS.

على سبيل المثال ، يحتوي كل كائن JS على فتحة [[Prototype]] داخلية وأسلوب [[GetOwnProperty]] داخلي.

لا تتوفر الفتحات والأساليب الداخلية في JS. على سبيل المثال ، لا يمكننا الوصول إلى o. [[Prototype]] أو استدعاء o. [[GetOwnProperty]] (). يمكن لمحرك JS أن ينفذها لتلبية احتياجاته (الداخلية) الخاصة به ، ولكن ليس مطلوبًا للقيام بذلك.

في بعض الأحيان تصبح الأساليب الداخلية عمليات مجردة بنفس الاسم ، كما هو الحال مع [[GetOwnProperty]]:

[[GetOwnProperty]] (P)

عندما يتم استدعاء الطريقة الداخلية [[GetOwnProperty]] للكائن "O" مع المفتاح "P" ، يتم تنفيذ الإجراءات التالية: OrdinaryGetOwnProperty ليست طريقة داخلية ، لأنها غير مرتبطة بأي كائن ؛ يتم تمرير الكائن الذي يعمل معه كمعلمة. تسمى OrdinaryGetOwnProperty "عادية" لأنها تعمل على كائنات عادية. الأشياء في ECMAScript عادية وغير عادية (غريبة). يكون الكائن عاديًا إذا تصرف بشكل يمكن توقعه استجابةً لمجموعة من الأساليب تسمى الطرق الداخلية الأساسية. خلاف ذلك (عندما يتصرف الكائن بشكل غير متوقع ؛ ليس كما هو متوقع ؛ عندما ينحرف سلوك الجسم عن الطبيعي ، يكون منحرفًا) ، يعتبر غير عادي.

  1. ! OrdinaryGetOwnProperty(O, P)





أشهر كائن غير معتاد هو Array ، لأن خاصية "الطول" تتصرف بشكل غير قياسي: يمكن أن يؤدي تعيين هذه الخاصية إلى إزالة العناصر من الصفيف.

يمكن العثور على قائمة بالأساليب الداخلية الأساسية هنا .

سجل الإنجاز


ماذا عن علامات الاستفهام والتعجب؟ لفهم هذا ، تحتاج إلى فهم ما هو سجل الإنجاز .

سجل الإنجاز هو نوع خاص (محدد فقط لأغراض المواصفات). محرك JS ليس مطلوبًا أن يكون له نفس نوع البيانات الداخلية.

سجل الاكتمال هو نوع بيانات يحتوي على مجموعة ثابتة من الحقول المسماة. يحتوي سجل الإنجاز على ثلاثة حقول:
[[نوع]]normal, break, continue, return throw. , normal, « () » (abrupt comlpetions)
[[Value]], , , , ,
[[Target]]( )

تُرجع كل عملية تجريدية بشكل ضمني سجل إكمال. حتى إذا كانت نتيجة العملية المجردة هي قيمة منطقية بسيطة ، يتم لفها في سجل إكمال من النوع العادي (انظر قيم الإكمال الضمني ).

ملاحظة 1: المواصفات غير متسقة للغاية في هذا الجزء ؛ هناك العديد من وظائف المساعد التي تقوم بإرجاع القيم العارية المستخدمة كما هي ، دون استردادها من سجل الإكمال.

ملاحظة 2: يسعى مؤلفو المواصفات إلى جعل معالجة سجل الإنجاز أكثر وضوحًا.

إذا كانت الخوارزمية تطرح استثناءً ، فهذا يعني أنه سيتم استلام سجل إكمال مع رمي النوع [[Type]]) والقيمة ([[Value]]) ككائن استثناء. لن نفكر في أنواع أخرى (فاصل ، الاستمرار والعودة) في الوقت الحالي.

ReturnIfAbrupt (الوسيطة) يعني تنفيذ العمليات التالية: هذا هو سجل الإكمال ؛ إذا انتهى فجأة ، يعود على الفور. خلاف ذلك ، نقوم باستخراج القيمة من سجل الإنجاز. ReturnIfAbrupt تبدو استدعاء دالة ، لكنها ليست كذلك. نحن نستدعي دالة تُرجع ReturnIfAbrupt () ، وليس دالة ReturnIfAbrupt نفسها. سلوكه أشبه ماكرو في لغات البرمجة مثل C. يمكن استخدام ReturnIfAbrupt على النحو التالي: هنا يأتي دوره

  1. argument - (abrupt), argument.
  2. argument argument.[[Value]].







  1. obj Foo() (obj - ).
  2. ReturnIfAbrupt(obj).
  3. Bar(obj) ( , , obj - , ).

علامة استفهام : سجل  ؟ يساوي Foo () ReturnIfAbrupt (Foo ()). استخدام هذا الاختصار له قيمة عملية: لسنا بحاجة إلى كتابة رمز معالج الخطأ في كل مرة.

قياساً على ذلك ، فليكن فال هو الإدخال ! Foo () يعادل ما يلي: باستخدام هذه المعرفة ، يمكننا إعادة كتابة Object.prototype.hasOwnProperty على النحو التالي: Object.prototype.hasOwnProperty (P) ... HasOwnProperty يمكن إعادة كتابته على النحو التالي : HasOwnProperty (O، P) يمكننا أيضًا إعادة كتابة الطريقة الداخلية [ [GetOwnProperty]] بدون علامة تعجب: O. [[GetOWnProperty]] نفترض أن temp هو متغير مؤقت جديد لا يتفاعل مع أي شيء.

  1. val Foo().
  2. : val .
  3. val val.[[Value]].





  1. P ToProperty(V).
  2. P , P.
  3. P P.[[Value]].
  4. O ToObject( this).
  5. O , O.
  6. O O.[[Value]].
  7. temp HasOwnProperty(O, P).
  8. temp , temp.
  9. temp temp.[[Value]].
  10. NormalCompletion(temp).





  1. : Type(O) Object.
  2. : IsPropertyKey(P) true.
  3. desc O.[[GetOWnProperty]](P).
  4. desc , desc.
  5. desc desc.[[Value]].
  6. desc undefined, NormalCompletion(false).
  7. NormalCompletion(true).





  1. temp OrdinaryGetOwnProperty(O, P).
  2. : temp .
  3. temp temp.[[Value]].
  4. NormalCompletion(temp).



نحن نعلم أيضًا أنه في الحالة التي ترجع فيها عبارة الإرجاع شيئًا غير سجل الإكمال ، فإن هذا الشيء يلتف ضمنيًا في الإكمال العادي.

احتياطي: العودة؟ فو ()


هل تستخدم المواصفات عودة؟ Foo () - لماذا توجد علامة استفهام هنا؟ عودة

قياسية ؟ يمكن توسيع Foo () على النحو التالي: سلوك الإرجاع؟ Foo () هو نفسه لكل من الإنهاء الطبيعي والمفاجئ. عودة قياسية؟ يسمح لك Foo () بالإشارة بشكل أوضح إلى أن Foo يُرجع سجل إكمال.

  1. temp Foo().
  2. temp , temp.
  3. temp temp.[[Value]].
  4. NormalCompletion.





صياغات


البيانات في المواصفات "تؤكد" الشروط الثابتة للخوارزميات. تتم إضافتها إلى مواصفات الوضوح ، ولكنها لا تحتوي على أي متطلبات للتنفيذ ؛ وبالتالي ، لا يلزم التحقق منها بواسطة تنفيذ معين.

ماذا بعد؟


تعلمنا قراءة مواصفات الطرق البسيطة مثل Object.prototype.hasOwnProperty والعمليات المجردة مثل HasOwnProperty. من خلال هذه المعرفة ، يمكننا أن نفهم ما تفعله العمليات المجردة الأخرى ، والتي سيتم مناقشتها في الجزء التالي. أيضًا في المقالة التالية ، سننظر في واصفات الملكية ، وهي نوع خاص آخر.


شكرآ لك على أهتمامك. الترميز سعيدة!

All Articles