المسارات
/
JavaScript
JavaScript
/
التمارين
/
مدينة الملاهي
مدينة الملاهي

مدينة الملاهي

تمرين تعلّمي

مقدمة

على عكس كثير من اللغات الأخرى، يوجد في JavaScript كيانان مختلفان يمثلان غياب قيمة (ذات معنى). هما null وundefined.

القيمة null

تُستخدم القيمة الأولية null كـ«قيمة فارغة» مقصودة للمتغيرات من أي نوع.

let name = null;
// name is intentionally set to "empty" because it is not
// available

يمكنك التحقق مما إذا كان المتغير يحمل القيمة null باستخدام عامل المساواة الصارم ===.

let name = null;

name === null;
// => true

القيمة undefined

المتغير الذي لم تُسنَد إليه قيمة يكون من النوع undefined.1

وهذا يعني أنه بينما تمثل null قيمة فارغة (لكنها قيمة رغم ذلك)، تمثل undefined الغياب التام للقيمة. 🤯

تظهر undefined في سياقات مختلفة.

  • إذا أُعلن عن متغير دون قيمة (أي دون تهيئة)، فإنه يكون undefined.
  • إذا حاولت الوصول إلى قيمة لمفتاح غير موجود في كائن، فستحصل على undefined.
  • إذا لم تُرجع دالة قيمة، فإن النتيجة تكون undefined.
  • إذا لم يُمرَّر وسيط إلى دالة، فإنه يكون undefined، إلا إذا كان لهذا الوسيط قيمة افتراضية.
let name;
console.log(name);
// => undefined

يمكنك التحقق مما إذا كان المتغير يحمل القيمة undefined باستخدام عامل المساواة الصارم ===.

let name;

name === undefined;
// => true

التسلسل الاختياري

إذا حاولت استرجاع قيمة متداخلة في كائن لكن المفتاح الأب غير موجود، فسيُلقي JavaScript خطأً. ولتجنب ذلك بسهولة، أُضيف التسلسل الاختياري إلى مواصفات اللغة في عام 2020. باستخدام عامل التسلسل الاختياري ?. يمكنك أن تضمن ألا يحاول JavaScript الوصول إلى المفتاح المتداخل إلا إذا لم يكن المفتاح الأب null أو undefined. وفي غير ذلك، تكون النتيجة undefined.

const obj = {
  address: {
    street: 'Trincomalee Highway',
    city: 'Batticaloa',
  },
};

obj.address.zipCode;
// => undefined

obj.residence.street;
// => TypeError: Cannot read property 'street' of undefined

obj.residence?.street;
// => undefined

الدمج الفارغي

هناك حالات تريد فيها تطبيق قيمة افتراضية إذا كان المتغير null أو undefined (وفي هذه الحالة فقط). ولمعالجة ذلك، قُدِّم عامل الدمج الفارغي ?? في عام 2020. فهو يُرجع الطرف الأيمن فقط عندما يكون الطرف الأيسر null أو undefined. وفي غير ذلك، يُرجع الطرف الأيسر.

let amount = null;
amount = amount ?? 1;
// => 1

amount = 0;
amount = amount ?? 1;
// => 0

[1] Undefined، MDN. (2021). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined (تاريخ الوصول: 4 يونيو 2021).

التعليمات

تقع على عاتقك مسؤولية توفير أجزاء من نظام المعلومات في مدينة ملاهٍ وصيانتها. وبشكل خاص، أنت مسؤول عن البرنامج الذي يدير الزوار والتذاكر.

أولًا، ستنشئ زائرًا جديدًا في النظام. ثم توفّر دالة لإبطال تذكرة. وفي المهمتين 3 و4، ستعمل على نظام تتبّع التذاكر الذي يساعد على منع التزوير. وأخيرًا، ستساعد في تكييف النظام مع متطلبات قانونية جديدة.

1. إنشاء زائر جديد

عندما يأتي الزوار إلى مدينة الملاهي للمرة الأولى، يحتاجون إلى التسجيل بإدخال اسمهم وعمرهم في الطرفية والموافقة على الشروط والأحكام. وبالطبع، يحتاجون أيضًا إلى شراء تذكرة. ولكل تذكرة معرّف مثل H32AZ123.

اكتب دالة createVisitor تستقبل ثلاثة وسائط.

  • اسم الزائر.
  • عمر الزائر.
  • معرّف التذكرة التي اشتراها الزائر.

ينبغي أن تُرجع الدالة كائنًا يحمل هذه المعلومات. وينبغي أن تُسمّى المفاتيح في الكائن name وage وticketId.

createVisitor('Verena Nardi', 45, 'H32AZ123');
// => { name: 'Verena Nardi', age: 45, ticketId: 'H32AZ123' }

2. إبطال التذكرة

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

وهذا يعني أنه عندما يغادر زائر الحديقة، ينبغي إبطال تذكرته فقط، مع بقاء بقية كائن الزائر كما هو. نفّذ الدالة revokeTicket التي تستقبل كائن زائر، وتضبط معرّف التذكرة على null، ثم تُرجع الكائن بعد ذلك.

const visitor = {
  name: 'Verena Nardi',
  age: 45,
  ticketId: 'H32AZ123',
};

revokeTicket(visitor);
// => { name: 'Verena Nardi', age: 45, ticketId: null }

3. تحديد حالة التذكرة

لمنع التزوير، تكون معرّفات التذاكر فريدة. وبمجرد طباعة تذكرة، يُضاف معرّفها كمفتاح في كائن داخل النظام حتى يمكن تتبّعها.

قبل بيع التذكرة لزائر، تُخزَّن بالقيمة null في كائن تتبّع التذاكر. وعند بيعها لزائر، يُسنَد اسم الزائر كقيمة لها. وعندما يشك الموظفون في صلاحية تذكرة، يحتاجون إلى التحقق من حالة التذكرة في النظام.

نفّذ دالة ticketStatus تستقبل كائن التتبّع ومعرّف تذكرة كوسيطين. ينبغي أن تُرجع إحدى النتائج التالية.

  • 'unknown ticket id' إذا لم يُعثر على المعرّف في كائن التتبّع
  • 'not sold' في حال طُبعت التذكرة ولكن لم تُبَع
  • 'sold to {name}' حيث {name} هو اسم الزائر إذا بيعت التذكرة
const tickets = {
  '0H2AZ123': null,
  '23LA9T41': 'Verena Nardi',
};

ticketStatus(tickets, 'RE90VAW7');
// => 'unknown ticket id'

ticketStatus(tickets, '0H2AZ123');
// => 'not sold'

ticketStatus(tickets, '23LA9T41');
// => 'sold to Verena Nardi'

4. تحسين استجابة حالة التذكرة

بعد فترة، تصلك ملاحظات من الموظفين بأنهم يريدون أن تكون حالة التذكرة أسهل في الفهم من النظرة الأولى. وهم يريدون فقط رؤية اسم الزائر أو أن التذكرة غير صالحة.

اكتب دالة simpleTicketStatus تستقبل الوسائط نفسها التي تستقبلها ticketStatus في المهمة 3. وهذه الدالة تُرجع واحدًا فقط من نتيجتين مختلفتين.

  • اسم الزائر إذا بيعت التذكرة
  • 'invalid ticket !!!' إذا لم تُبَع التذكرة بعد أو لم يُعثر على المعرّف في كائن التتبّع
const tickets = {
  '0H2AZ123': null,
  '23LA9T41': 'Verena Nardi',
};

simpleTicketStatus(tickets, '23LA9T41');
// => 'Verena Nardi'

simpleTicketStatus(tickets, '0H2AZ123');
// => 'invalid ticket !!!'

simpleTicketStatus(tickets, 'RE90VAW7');
// => 'invalid ticket !!!'

5. تحديد إصدار الشروط والأحكام

بسبب متطلبات قانونية جديدة، تحتوي كائنات الزوار المُنشأة حديثًا الآن أيضًا على معلومات مفصّلة عن "الشروط والأحكام العامة" (GTC) التي وافق عليها المستخدم. يمكنك رؤية مثال على كائن الزائر الجديد أدناه.

يحتاج أمناء الصندوق في مدينة الملاهي الآن إلى التحقق مما إذا كان على زائر توقيع إصدار جديد من الشروط والأحكام العامة. ومن أجل ذلك، نفّذ دالة gtcVersion تستقبل كائن زائر كوسيط وتُرجع إصدار الشروط والأحكام العامة إذا كان متاحًا. وإذا لم تكن معلومات الإصدار متاحة، فلا ينبغي إرجاع أي شيء.

const visitorNew = {
  name: 'Verena Nardi',
  age: 45,
  ticketId: 'H32AZ123',
  gtc: {
    signed: true,
    version: '2.1',
  },
};

gtcVersion(visitorNew);
// => '2.1'

const visitorOld = {
  name: 'Verena Nardi',
  age: 45,
  ticketId: 'H32AZ123',
};

gtcVersion(visitorOld);
// => undefined
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
JavaScript Exercism

مستعد لبدء مدينة الملاهي؟

سجّل في Exercism لتتعلّم وتتقن JavaScript عبر 37 مفهومًا159 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.