اذهب إلى المحتوى

لوحة المتصدرين

  1. Ail Ahmed

    Ail Ahmed

    الأعضاء


    • نقاط

      8

    • المساهمات

      1199


  2. محمد عاطف17

    محمد عاطف17

    الأعضاء


    • نقاط

      5

    • المساهمات

      3123


  3. محمود سعداوي2

    محمود سعداوي2

    الأعضاء


    • نقاط

      5

    • المساهمات

      604


  4. Adnane Kadri

    Adnane Kadri

    الأعضاء


    • نقاط

      4

    • المساهمات

      5196


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 09/26/24 في كل الموقع

  1. السلام عليكم هو ليه بيحصل خطاء في الكود ده ؟ arr = [1,2,4,4] sm = 8 for i in range(0 , len(arr)): if arr[i] == arr[i+=1]: print("yes")
    2 نقاط
  2. السلام عليكم اي هي الخورزميا Divide and conquer ؟
    2 نقاط
  3. هل من الممكن أن أجد عمل حر أثناء دراستي في كلية الهندسة ويغطي مصاريفي كطالب بعد إتمام دورة الذكاء الاصطناعي ؟
    1 نقطة
  4. لماذا لا يشتغل المقطع و ما هوا الحل
    1 نقطة
  5. السلام عليكم عندي حل مسائل برمجه هل اكتفي بموقع واحد زي مثل Leetcode ؟ واي الفرق بين Leetcode وبين codewars ؟
    1 نقطة
  6. وعليكم السلام ورحمة الله وبركاته. نعم من الممكن حاليا الإكتفاء فقط بموقع واحد ولكن بالطبع مع تقدم مستواك الأفضل هو محاولة حل المسائل والمشكلات على مواقع كثيرة لإكتساب مهارة حل المشكلات حيث كل موقع يوفر نظام وأسئلة معينة ولذلك التنوع مطلوب. توجد العديد من المواقع الأخرى HackerRank وCodeforces والعديد منها ويمكنك قراءة الإجابة التالية لمواقع وتفاصيل أكثر : ولكن في البداية يفضل البدا بحل المسائل على موقع CodeWars فهو يتيح حل تحديات برمجية متعددة المستويات ويمكنك التقدم تدريجيا بها . أما موقع LeetCode يركز بشكل أكبر على التحضير للمقابلات التقنية والأسئلة الخاصة بالمقابلات ويحتوي على مشاكل مشابهة لتلك التي قد تواجهها في الشركات الكبرى و يقدم مجموعة واسعة من المشاكل المرتبطة بالبيانات والخوارزميات مع تصنيفها حسب الصعوبة. لهذا حاليا في المستوى المبتدأ يفضل الإكتفاء بموقع واحد وإذا قمت بإتمام المستوى الخاص بك حينها يمكنك الذهاب إلى موقع أخر وحل الأسئلة الخاصة بهذا المستوى . ومع تقدمك ستجد أنه أصبحت لديك مهارة حل المشكلات وحينها يمكنك الدخول إلى المستويات التالية والمتقدمة.
    1 نقطة
  7. السلام عليكم ده المسائل Collection of numbers and I need you to take this collection of numbers and find a maatching pair that is equal to a sum that i give you as well وده الحل بتاعي arr = [1,2,4,4] sm = 8 for i in range(len(arr) - 1): if arr[i] == arr[i+1]: if arr[i] + arr[i + 1] == sm: print(f"{arr[i]} + {arr[i + 1]} = {sm}") else: print("Not Found pair") المشكله هنا انا الIf و Else الاثينين بيشتغلو يعني هنا بيحصل خطاء منطقي الصراحه بس مش عارف احل الخطاء ده ازي ؟
    1 نقطة
  8. السلام عليكم. أود إنشاء الجداول في postegres فقمتكتابة الأمر التالي npx migrate prisma dev ظهر لي هذا الخطأ Environment variables loaded from .env Prisma schema loaded from prisma\schema.prisma Datasource "db": PostgreSQL database "**************@localhost:5432/CloudHostigDB", schema "public" at "postegres" Error: P1001: Can't reach database server at `postegres:5432` Please make sure your database server is running at `postegres:5432`. كيف يمكن معالجة هذا الخطأ. شكرا
    1 نقطة
  9. اعتقد أن المشكلة هنا في كلمة المرور حيث يجب أن يتم عمل encode لكلمة المرور بما أنها تحتوي على رموز مثل / و * . لذلك أولا يرجى تجربة إستبدال السطر لديك بالسطر التالي: DATABASE_URL="postgresql://postegres:%2F%2AMahmouD_1989%2A%2F/@localhost:5432/CloudHostingDB?schema=public" إذا ظلت المشكلة حاول تغير كلمة المرور لا تحتوى على رموز خاصة والمحاولة مرة أخرى.وإخبارى بالنتيجة.
    1 نقطة
  10. هذا ملف .env DATABASE_URL="postgresql://postegres:/*MahmouD_1989*/@localhost:5432/CloudHostingDB?schema=public" ملف schema.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) username String @db.VarChar(100) email String @unique password String isAdmin Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] } model Article { id Int @id @default(autoincrement()) title String @db.VarChar(200) description String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] } model Comment { id Int @id @default(autoincrement()) text String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt articleId Int userId Int // One-to-Many relation between Article & Comment article Article @relation(fields: [articleId], references: [id]) // One-to-Many relation between User & Comment user User @relation(fields: [userId], references: [id]) }
    1 نقطة
  11. إذا خادم قاعدة البيانات يعمل بشكل جيد ولا توجد به مشكلة. هل تأكدت من كتابة إسم قاعدة البيانات وإسم المستخدم وكلمة المرور بشكل صحيح ؟ من فضلك يرجى إرسال رابط قاعدة البيانات في الكود لديك الذي تحاول الإتصال به. ولكن أولا حاول إضافة connect_timeout=300 في نهاية رابط قاعدة البيانات كتالي : DATABASE_URL="postgres://postgres:postgres@localhost:5432/postgres?connect_timeout=300" وانظهر هل ذلك يحل المشكلة أم لا.
    1 نقطة
  12. مرحبا مجددا هذا ما ظهر لي عند تنفيذ الأمر npx prisma migrate dev ظهر نفس الخطأ مجددا
    1 نقطة
  13. اضف المتغير psql الى متغيرات البيئة في ويندوز لديك، أو نفذ مباشرة: C:\PostgreSQL\9.2\bin -h localhost -U username -d CloudHostingDB
    1 نقطة
  14. 1 نقطة
  15. افتح نافذة CMD وشغل الأمر: psql -h localhost -U username -d CloudHostingDB استبدل بياناتك وانظر ما ان كان يتم الاتصال بصورة صحيحة.
    1 نقطة
  16. وعليكم السلام، الخطأ الذي ظهر لك يشير إلى أن Prisma غير قادر على الاتصال بخادم قاعدة البيانات PostgreSQL على العنوان postegres:5432. يبدو أن هناك خطأ في اسم المضيف (host) المكتوب في ملف البيئة .env. يجب أن يكون اسم المضيف الصحيح هو localhost أو اسم المضيف الفعلي لخادم PostgreSQL. لإصلاح الخطأ، تأكد من: أن إعداد DATABASE_URL مكتوب بشكل صحيح. تحقق من تشغيل قاعدة البيانات. تحقق من الاتصال بقاعدة البيانات.
    1 نقطة
  17. وعليكم السلام، المشكلة التي تواجهك هي أنك لا تتحكم في كيفية تداخل الشروط بشكل صحيح، وبالتالي تظهر الرسالة "Not Found pair" حتى عندما تجد الزوج المطلوب. يجب عليك تصحيح منطقك في الحل بحيث تظهر رسالة "Not Found pair" فقط بعد البحث عن كل الأزواج وعدم العثور على أي منهم. إليك الشيفرة معدلة: arr = [1, 2, 4, 4] sm = 8 found = False # متغير لتحديد إذا ما كان وجدنا زوجًا مناسبًا أم لا # التحقق من كل زوج من الأرقام for i in range(len(arr)): for j in range(i + 1, len(arr)): if arr[i] + arr[j] == sm: print(f"{arr[i]} + {arr[j]} = {sm}") found = True # إذا وجدنا زوجًا، نغير قيمة found # إذا لم يتم العثور على أي زوج if not found: print("Not Found pair") سيفي هذا بالغرض ويضمن لنا أن الرسالة لن تظهر إلا بعد عدم العثور رعلى زوج.
    1 نقطة
  18. المشكلة لديك في المقارنة حيث أنarr[i+=1] ليست صيغة صحيحة في بايثون و يجب عليك حذف علامة تساوي ليصبح الكود هكذا: if arr[i] == arr[i+1]: و بالنسبة للكود النهائي يمكنك تعديله بهذا الشكل: arr = [1, 2, 4, 4] sm = 8 for i in range(len(arr) - 1): if arr[i] == arr[i + 1]: print("yes") لاحظ أنني قمت بتعديل الحلقة ليكون طولها len(arr) - 1 حتى لا نحاول الوصول إلى عنصر خارج النطاق عند مقارنة arr[i + 1]
    1 نقطة
  19. الخطأ في هذا السطر: if arr[i] == arr[i+=1]: إذا كنت ترغب في مقارنة العنصر الحالي بالعنصر التالي، يجب تعديل الكود ليصبح بالشكل التالي: if arr[i] == arr[i + 1]:
    1 نقطة
  20. السلام عليكم هو الLinked list و stacks و Queues و الmaps و Heaps حاجت مهم اتعلمها حتي لو انا باستخدم لغة باثيون ؟ والا الا ده حاجت خاص باهياكل البيانات فالازم اتاسس فيهم بغض النظر عن لغة البرمجه ؟ واي هو الmaps والHeaps ؟
    1 نقطة
  21. وعليكم السلام ورحمة الله وبركاته. إن Divide and Conquer هي استراتيجية تصميم للخوارزميات حيث تعتمد على تقسيم المشكلة الكبيرة إلى مشكلات أصغر يمكن حلها بشكل منفصل ثم يتم دمج تلك الحلول المنفردة للحصول على حل للمشكلة الأصلية (الكبيرة). مثال مبسط لكيفية إستخدام تلك الإسترتيجية في حل مشكلة الترتيب . خوارزمية الدمج (Merge Sort): تستخدم هذه الخواريزمية لترتيب العناصر حيث نقوم بتقسيم القائمة إلى نصفين وترتيب كل نصف بشكل منفصل ثم يتم دمج القائمتين معا في النهاية.
    1 نقطة
  22. بالنسبة لخوارزمية "Divide and Conquer" أو بما تسمى التقسيم والتغلب فهي تقنية تستخدم في تصميم الحلول لمشاكل معينة عن طريق تقسيم المشكلة إلى أجزاء أصغر وأكثر سهولة في الحل، و بعد تقسيم المشكلة الكبيرة إلى أجزاء أصغر، يتم حل كل جزء على حدة، ثم يتم دمج النتائج لحل المشكلة الأساسية بشكل كامل. حيث نقوم أولا بتقسيم المشكلة الكبيرة إلى مشكلات أصغر تكون شبيهة بالمشكلة الأصلية ولكن أصغر في الحجم، و من ثم في مرحلة التغلب نقوم بحل كل مشكلة صغيرة على حدة، إذا كانت المشكلة بسيطة بدرجة كافية، يتم حلها مباشرة، وإلا يتم تكرار العملية على المشكلات الأصغر، و بعد حل المشكلات الأصغر، يتم دمج النتائج لإعطاء الحل النهائي للمشكلة الأصلية، بهذا الشكل:
    1 نقطة
  23. تعلم هياكل البيانات مهم جدًا، حتى لو كنت تستخدم لغة Python. هذه المفاهيم أساسية في علوم الكمبيوتر وهي مهمة بغض النظر عن لغة البرمجة التي تستخدمها. ولاحظ أنه بالرغم من أن Python توفر العديد من هياكل البيانات المدمجة مثل القوائم والقواميس، إلا أن فهم هذه الهياكل الأساسية سيساعدك على: فهم كيفية عمل الهياكل المدمجة في Python بشكل أفضل. اختيار الهيكل الأنسب لحل مشكلة معينة. فهم خوارزميات معقدة تعتمد على هذه الهياكل. بالنسبة لـ Maps في Python، يتم تمثيل Maps بواسطة القواميس (Dictionaries). وهي هياكل بيانات تخزن أزواج من المفاتيح والقيم و تسمح بالوصول السريع إلى البيانات باستخدام المفاتيح. أما بالنسبة لل Heaps فهي نوع خاص من الأشجار الثنائية. وفي Python، يمكنك استخدام وحدة heapq لتنفيذ الأكوام. وعتبر مفيدة في الخوارزميات التي تتطلب الوصول السريع إلى العنصر الأكبر أو الأصغر. تعلم هذه الهياكل سيساعدك على فهم أعمق للبرمجة وحل المشكلات بشكل أكثر كفاءة، بغض النظر عن لغة البرمجة التي تستخدمها. في Python، قد لا تحتاج إلى تنفيذ هذه الهياكل من الصفر في كثير من الأحيان، ولكن فهمها سيساعدك على استخدام المكتبات والأدوات المتاحة بشكل أفضل.
    1 نقطة
  24. وعليكم السلام ورحمة الله وبركاته. نعم بالطبع تعلم هياكل البيانات Data Structure هو شئ مهم حيث سيجعل لك الخبرة في كيفية التعامل مع البيانات والطريقة الأفضل للتعامل مع كل نوع بيانات . وأيضا كيفية التعامل مع الذاكرة وتقيم سرعة الكود الخاص بك وكيفية تحسينه والمتطلبات اللازمة لذلك . وأيضا سيعطيك الخبرة في حل المشكلات حيث كل نوع من أنواع هياكل البيانات يساعد في حل مشكلة معينة و يستخدم لأغراض معينة لذلك بالطبع عليك تعلمهم مهما كانت اللغة التي تعمل عليها . ويمكنك بعد تعلمهم محاولة إنشاءه من خلال كود بايثون بنفسك فهذا الشئ جيد وسيفيدك كثيرا. أما بخصوص ال maps او القواميس (الـDictionaries في بايثون) هي نوع من أنواع هياكل البيانات حيث يتم تخزين البيانات في شكل أزاوج مكونه من مفاتح وقيمة لذلك المفتاح حيث يمكنك الوصول إلى تلك القيمة من خلال المفتاح الخاص بها. my_map = { "mohamed": 1, "ahmed": 2, "mahmoud": 3 } print(my_map["mohamed"]) أما ال Heap فهو نوع خاص من الأشجار (binary tree) حيث يُستخدم بشكل رئيسي لتنفيذ خوارزميات الفرز والبحث والترتيب. ويمكنك قراءة الإجابات التالية لمزيد من التفاصيل :
    1 نقطة
  25. بالتأكيد عند إكمال هذه الدورة، ستمتلك المهارات التي تؤهلك للعمل في مجال الذكاء الاصطناعي، لكن نجاحك يعتمد أيضًا على التزامك بتطبيق ما تعلمته من خلال بناء المشاريع التي تشملها الدورة، والبحث عن وظيفة بجدية واحترافية. ولا تترك الأكاديمية المهمة عند تعليمك فقط إنما ستحصل على دعم من مركز المساعدة، الذي يساعدك في إعداد سيرة ذاتية متميزة. أما في حال لم تتمكن من العثور على وظيفة بعد الدورة، يمكنك استرداد المبلغ المدفوع بالكامل دون أي تعقيد.
    1 نقطة
  26. من فضلكم اريد ان احصل علي مصادر لمعرفه أكثر عن Webpack Node.js npm المعلومات في الكورس الواجهه الاماميه Front - Endغير كافيه ولكم الشكر
    1 نقطة
  27. توفر أكاديمية حسوب ضمان لإسترداد كامل سعر الدورة في حالة أنك أنهيت الدورة ولم تجد أي عمل لمدة ستة أشهر من وقت إتمام الدورة و هذا ما يميز الدورات هنا، حيث هناك فريق مختص سيساعدك على إيجاد عمل في أسرع وقت ممكن و يمكنك الإطلاع على صفحة الأسئلة الشائعة ليكون لديك فكرة أفضل على الدورات.
    1 نقطة
  28. السلام عليكم .. لقد حدثت صورتي الشخصية في الموقع ولم تظهر حتي الان ؟
    1 نقطة
  29. نعم يوجد، مسابقة ACPC كان النهائي السنة الماضية للمسابقة الإفريقية و العربية في مصر، و أعتقد أن هذه السنة لم تبدأ بعد يمكنك البحث عليها لمعرفة كيفية التسجيل، و على الأغلب فهي موجهة لطلاب الجامعة.
    1 نقطة
  30. نلقي نظرة في هذا المقال على الصياغة اﻷساسية لكائن جافا سكريبت كما نستذكر بعض الميزات التي ناقشناها سابقًا لنشدد على حقيقة أن العديد من الميزات التي اطلعنا عليها وتعاملنا معها في لغة جافا سكريبت هي في الواقع كائنات، ابتداءً من المميزات البنيوية للغة مثل المصفوفات إلى الواجهات البرمجية للمتصفحات APIs المبنية على أساس جافا سكريبت. وبإمكانك أيضًا بناء كائنات خاصة بك لتغليف مجموعة من الدوال والمتغيرات ضمن حزمة أكثر فعالية تعمل كحاوية بيانات. ولا بد أن تتفهم طبيعة جافا سكريبت القائمة على الكائنات إن أردت التعمق أكثر في تعلم هذه اللغة، لهذا نزوّدك ضمن هذا المقال والمقالات التالية بمعلومات مهمة عن الكائنات البرمجية وصياغتها بشيء من التفصيل ثم ننتقل إلى شرح طريقة بناء كائنات خاصة بك. ننصحك قبل أن تبدأ العمل معنا في هذه السلسلة أن تطلع على: أساسيات HTML أساسيات عمل CSS أساسيات جافا سكريبت أساسيات الكائنات الكائن object هو مجموعة مترابطة من البيانات أو الوظائف، فهو يتألف عادة من من عدة متغيرات ودوال (تُدعى المتغيرات ضمن الكائن خاصيات properties والدوال methods). وحتى نستوعب مفهوم الكائنات سنعمل على المثال التالي. أنشئ أولًا نسخة من الملف oojs.html على حاسوبك. ويتضمن هذا الملف العنصر <script> الذي سنكتب ضمنه الشيفرة. سنستخدم هذه الصفحة كأساس لاستكشاف الصياغة اﻷساسية للكائن في جافا سكريبت. وعليك أن تفتح طرفية جافا سكريبت الخاصة بأدوات مطوري ويب وتجعلها جاهزة لكتابة التعليمات. وكما هو الحال في الكثير من اﻷشياء في جافا سكريبت، يبدأ إنشاء الكائن بتعريف وتهيئة بعض المتغيرات. لهذا جرّب إدخال السطر التالي تحت السطر الموجود أصلًا في ملف التمرين ثم احفظ التغييرات وأعد تحميل الصفحة: const person = {}; افتح اﻵن طرفية جافا سكريبت ثم اكتب person ضمنها ثم اضغط المفتاح Enter. من المفترض أن تحصل على نتيجة مشابهة للتالي: [object Object] Object { } { } تهانينا! لقد أنشأت للتو كائنًا في جافا سكريبت. لقد أنجز العمل بالفعل، لكن الكائن فارغ كما تلاحظ ولا يمكن أن يفيدنا كثيرًا. لهذا سنعدّل الكائن ضمن شيفرة جافا سكريبت في ملف التمرين كالتالي: const person = { name: ["Bob", "Smith"], age: 32, bio: function () { console.log(`${this.name[0]} ${this.name[1]} is ${this.age} years old.`); }, introduceSelf: function () { console.log(`Hi! I'm ${this.name[0]}.`); }, }; جرّب إدخال بعض التعليمات كما يلي في طرفية جافا سكريبت وذلك بعد حفظ التغييرات وإعادة تحميل الصفحة: person.name; person.name[0]; person.age; person.bio(); // "Bob Smith is 32 years old." person.introduceSelf(); // "Hi! I'm Bob." يضم الكائن بعض البيانات اﻵن كما يحتوي على بعض الوظائف التي يمكن الوصول إليها من خلال صياغة بسيطة واضحة. ما الذي يحدث فعلًا في مثالنا؟ لقد أنشأنا كائنًا مكوّنًا من عدة أعضاء members لكل منها اسم ( مثال name و age) وقيمًا مثل ['Bob, 'Smiths] و 32. يفصل بين كل زوج (اسم/قيمة) فاصلة ,، وبين كل اسم وقيمة نجد نقطتين متعامدتين :. وتتبع صياغة الكائن الشكل التالي دائمًا: const objectName = { member1Name: member1Value, member2Name: member2Value, member3Name: member3Value, }; قد تكون قيمة أعضاء الكائن أي شيء، وفي مثالنا السابق ضم الكائن person أعدادًا ومصفوفة ودالتين. إن أول عضوين كما رأينا يضمان بيانات عن الكائن ويُشار إليهما كخاصيات properties، كما يُشار إلى الدالتين اللتان تسمحان للكائن بتنفيذ بعض العمليات على البيانات بالتوابع أو الدوال التابعة للكائن methods. وعندما يكون عضو الكائن دالة، باﻹمكان استخدام صياغة أبسط من bio:function، ويكفي أن نكتب ()bio كالتالي: const person = { name: ["Bob", "Smith"], age: 32, bio() { console.log(`${this.name[0]} ${this.name[1]} is ${this.age} years old.`); }, introduceSelf() { console.log(`Hi! I'm ${this.name[0]}.`); }, }; وسنستخدم من اﻵن وصاعدًا الصيغة المختصرة في تعريف الدوال. ندعو الكائنات التي تُبنى كما شرحنا سابقًا بالكائنات الحرفية literal object لأننا كتبنا حرفيًا كل أعضائها عند إنشائها. وهي كائنات مختلفة عن تلك التي تُنسخ عن اﻷصناف، والتي سنلقي عليها نظرة لاحقًا. من الشائع أيضًا إنشاء الكائنات كنسخ عن الكائنات الحرفية، وخاصة عندما نريد نقل سلسلة من البيانات المهيكلة المترابطة مثل إرسال طلب إلى خادم لوضع البيانات ضمن قاعدة بيانات. فإرسال كائن واحد أكثر فعالية من إرسال البيانات بشكل مستقل ومن اﻷسهل التعامل معها موازنة بالتعامل مع مصفوفة عندما تريد تحديد كل عنصر باسمه بشكل مستقل. طريقة النقطة Dot notation للوصول إلى أعضاء الكائن لقد وصلنا في مثالنا السابق إلى خاصيات وتوابع الكائن باستخدام العامل . ويسمى هذا الأسلوبالتدوين النقطي أو الاستدعاء النقطي dot notation. حيث يسلك اسم الكائن person سلوك فضاء الأسماء namespace. ولا بد من كتاب اسم الكائن أولًا للوصول إلى أي عضو من أعضاءه ومن ثم تكتب النقطة ومن ثم العضو الذي تريد الوصول إليه، وقد يكون العضو عنصرًا أو مصفوفة أو استدعاء أحد توابع الكائن. person.age; person.bio(); الكائنات والخاصيات على شكل كائنات يمكن للخاصية بحد ذاتها أن تكون كائنًا، جرّب مثلًا أن تغيّر العضو name من الشكل التالي: const person = { name: ["Bob", "Smith"], }; ليصبح بالشكل: const person = { name: { first: "Bob", last: "Smith", }, // … }; وللوصول إلى هذه العناصر لا بد من ربطها بالكائن الرئيسي بكتابة نقطة أخرى. جرّب كتابة الشيفرة التالية في طرفية جافا سكريبت: person.name.first; person.name.last; فإن فعلت ذلك، عليك العودة إلى الشيفرة وتغيير كل شيفرة من الشكل: name[0]; name[1]; إلى name.first; name.last; وإلا لن تعمل التوابع. استخدام طريقة اﻷقواس في الوصول إلى أعضاء الكائن باﻹمكان الوصول إلى أعضاء الكائن باستخدام طريقة اﻷقواس المربعة Bracket notation فبدلًا من استخدام النقطة كما في المثال التالي: person.age; person.name.first; يمكننا استخدام الأقواس كما في الكود التالي: person["age"]; person["name"]["first"]; يبدو اﻷمر مشابهًا للوصول إلى عناصر مصفوفة، هو من ناحية المبدأ اﻷمر ذاته، فبدلًا من الوصول باستخدام دليل المصفوفة index، تستخدم الاسم المرتبط بقيمة العنصر. لهذا السبب تًدعى الكائنات أحيانًا مصفوفات ترابطية associative arrays، فهي ترتبط بالقيم النصية بنفس الطريقة التي ترتبط فيها المصفوفة بدليلها. يُفضّل استخدام طريقة النقطة على طريقة اﻷقواس عمومًا لأنها أكثر وضوحًا وأسهل قراءة. لكن ستجد بعض الحالات التي تستخدم فيها اﻷقواس المربعة مثل إسناد قيمة خاصية على شكل كائن إلى متغيّر، فلن تستطيع في هذه الحالة استخدام النقطة للوصول إلى القيمة، لكن باﻹمكان استخدام الأقواس المربعة. في المثال التالي، يمكن للدالة أن تستخدم الطريقة person[propertyName] للوصول إلى القيمة المخزنة في الخاصية proertyName: const person = { name: ["Bob", "Smith"], age: 32, }; function logProperty(propertyName) { console.log(person[propertyName]); } logProperty("name"); // ["Bob", "Smith"] logProperty("age"); // 32 ضبط قيم أعضاء الكائن كل ما تعلمناه حتى اللحظة هو الحصول على قيمة أعضاء الكائن object members، لكن باﻹمكان أيضًا ضبط قيمة هذه الأعضاء بالتصريح عن العضو الذي تريد ضبطه (باستخدام طريقة النقطة أو اﻷقواس المربعة) كالتالي: person.age = 45; person["name"]["last"] = "Cratchit"; جرّب إدخال التعليمتين التاليتين ضمن طرفية جافا سكريبت، ولاحظ كيف تغيرت القيمة: person.age; person["name"]["last"]; لا يقتصر ضبط قيم أعضاء الكائن على تغيير القيمة الموجودة للخاصيات أو التوابع، بل يمكنك إنشاء عناصر جديدة كليًا. جرّب اﻵن ما يلي في الطرفية: person["eyes"] = "hazel"; person.farewell = function () { console.log("Bye everybody!"); }; اختبر اﻵن العناصر الجديدة: person["eyes"]; person.farewell(); // "Bye everybody!" من إيجابيات استخدام طريقة اﻷقواس المربعة أنه باﻹمكان استخدامها في ضبط قيمة اﻷعضاء ديناميكيًا إضافة إلى تغيير أسماء الأعضاء أيضًا. لنفترض أننا نريد منح المستخدم القدرة على تخزين أنواع مخصصة من القيم في بيانات اﻷشخاص وذلك بكتابة اسم العضو وقيمته ضمن مربعي إدخال نصي منفصلين. باﻹمكان إنجاز اﻷمر كالتالي: const myDataName = nameInput.value; const myDataValue = nameValue.value; نضيف بعدها هذا العضو الجديد إلى الكائن person كالتالي: person[myDataName] = myDataValue; ولاختبار اﻷمر، جرّب إضافة الأسطر التالية إلى شيفرتك، أسفل قوس إغلاق الكائنن person: const myDataName = "height"; const myDataValue = "1.75m"; person[myDataName] = myDataValue; جرّب حفظ التغييرات وإعادة تحميل الصفحة ثم إدخال التالي ضمن مربع اﻹدخال النصي: person.height; إن إضافة خاصية إلى الكائن باستخدام اﻷسلوب السابق لن يكون ممكنًا باستخدام طريقة النقطة والتي تقبل فقط الاسم الحرفي للعضو ولا تقبل قيمة متغير يشير إلى الاسم. لماذا استخدمت الكلمة المحجوزة this لربما قد لاحظت شيئًا غريبًا في أسلوبنا في الشيفرة السابقة، ألق نظرة اﻵن على هذا المثال: introduceSelf() { console.log(`Hi! I'm ${this.name[0]}.`); } لربما تتساءل ماذا فعلت الكلمة this؟ تشير هذه الكلمة المحجوزة إلى الكائن الحالي الذي كُتبت الشيفرة ضمنه، فهي في مثالنا تكافئ الكائن person. لماذا إذًا لا نستخدم person وحسب؟ في الواقع، لا فائدة من استخدام الكلمة this كثيرًا في حال أنشأت كائن حرفي وحيد، لكن إن أنشأت أكثر من كائن حرفي، يساعدك ذلك في استخدام نفس تعريف التابع لكل كائن أنشأته. لنوضح ذلك من خلال المثال التالي: const person1 = { name: "Chris", introduceSelf() { console.log(`Hi! I'm ${this.name}.`); }, }; const person2 = { name: "Deepti", introduceSelf() { console.log(`Hi! I'm ${this.name}.`); }, }; في هذه الحالة، ينتج عن تنفيذ التعليمة ()person1.introduceSelf الخرج التالي "Hi! I'm Chris."، بينما ينتج عن تطبيق نفس التابع على كائن آخر ()person2.introduceSelf من نفس النوع خرج آخر مناسب للكائن "Hi! I'm Deepti". وعلى الرغم من أن الشيفرة نفسها في الحالتين، لكن أهميتها لن تظهر عند كتابة كائنات حرفية يدويًا، بل عندما تبدأ باستخدام الدوال البانية constructors ﻹنشاء أكثر من كائن من تعريف واحد له وهذا ما نناقشه تاليًا. مقدمة إلى الدوال البانية Constructors لا بأس باستخدام الكائنات الحرفية عندما تريد استخدام كائن واحد، لكن إن كان عليك إنشاء أكثر من عنصر سيغدو استخدام العناصر الحرفية غير ملائم. إذ علينا كتابة نفس الشيفرة لكل كائن على حدى، وإن كان علينا تغيير بعض الخاصيات كإضافة الخاصية height، لا بد من تذكرّ تغيير كل الكائنات التي أنشأتها. من الأفضل استخدام شكل أو نموذج للكائن يضم كافة التوابع والخاصيات اللازمة، ومن ثم إنشاء العدد الذي يلزمنا من هذا الكائن وفق هذا الشكل بتعديل قيم الخواص المختلفة. إليك نسخة أولى من الشكل الذي نتحدث عنه وهو على شكل دالة: function createPerson(name) { const obj = {}; obj.name = name; obj.introduceSelf = function () { console.log(`Hi! I'm ${this.name}.`); }; return obj; } تُنشئ الدالة وتعيد كائنًا جديدًا في كل مرة نستدعيها، ويضم هذا الكائن عضوين هما: الخاصية: name. التابع: ()introduceSelf. تأخذ الدالة ()createPersonمعاملًا وحيدًا هو name لضبط قيمة الخاصية name، لكن تبقى قيمة التابع ()introduceSelf نفسها لجميع الكائنات التي تنشأها الدالة. ويُعد هذا اﻷسلوب من أكثر الطرق شيوعًا في إنشاء الكائنات. بإمكانك اﻵن إنشاء العدد الذي تريده من الكائنات، بإعادة استخدام الدالة: const salva = createPerson("Salva"); salva.name; salva.introduceSelf(); // "Hi! I'm Salva." const frankie = createPerson("Frankie"); frankie.name; frankie.introduceSelf(); // "Hi! I'm Frankie." ستعمل الشيفرة السابقة جيدًا لكنها طويلة بعض الشيء. إذ أنشأنا كائنًا فارغًا ثم هيأناه وأعدناه، لكن الطريقة اﻷفضل تقضي باستخدام دالة بانية، وهي دالة نستدعيها باستخدام الكلمة المحجوزة new. وعندما نستدعي دالة بانية فإنها: تنشئ كائنًا جديدًا. تربط this بالكائن الجديد، وستتمكن عندها من اﻹشارة إلى الكائن الجديد من خلالها ضمن شيفرة الدالة البانية. تعيد الكائن الجديد. تبدأ أسماء الدوال البانية عادة بحرف كبير وتسمى باسم نوع الكائن الذي تنشؤه، لهذا سنعيد كتابة مثالنا ليصبح بالشكل التالي: function Person(name) { this.name = name; this.introduceSelf = function () { console.log(`Hi! I'm ${this.name}.`); }; } ولكي نستدعي الدالة ()Person كدالة بانية نستخدم الكلمة new: const salva = new Person("Salva"); salva.name; salva.introduceSelf(); // "Hi! I'm Salva." const frankie = new Person("Frankie"); frankie.name; frankie.introduceSelf(); // "Hi! I'm Frankie." لقد استخدمت الكائنات كثيرًا فيما مضى لربما تساءلت أثناء العمل على الأمثلة السابقة بأن استخدام النقطة كان مألوفًا، والسبب أنك استخدمتها طوال فترة تعلم جافا سكريبت عبر سلسلة مقالتنا. فكل مرة عملنا فيها مع مثال يستخدم واجهة المتصفح البرمجية أو كائنات جافا سكريبت، استخدمنا فيها الكائنات لأنها ميزات بنيت باستخدام الطريقة نفسها التي بنينا فيها الكائنات المخصصة في مثالنا اﻷخير، لكنها بالطبع أكثر تعقيدًا. فعندما تستخدم التابع النص كما في المثال التالي: myString.split(","); فأنت تستخدم التوابع التي يوفرّها الكائن String. وفي كل مرة تنشئ فيها سلسلة نصية في شيفرتك، سيتولد هذا النص تلقائيًا كنسخة عن الكائن String، ويشترك معه بالعدبد من الخاصيات والتوابع. وعندما تحاول الوصول إلى كائن المستند باستخدام شيفرة كالتالي: const myDiv = document.createElement("div"); const myVideo = document.querySelector("video"); فأنت تستخدم في الواقع التوابع التي يقدّمها الكائن أو الواجهة البرمجية Document، وعند كل تحميل لصفحة الويب تُنشئ نسخة جديدة عن هذا الكائن تُدعى document تمثّل هيكلية الصفحة بأكملها ومحتواها وغير ذلك من الميزات مثل عناوين URL. أي باختصار، سيمتلك الكائن الذي أنشأته عدة توابع وخاصيات يشترك فيها مع الكائن الأساسي Document. وهذا الأمر مشابه للكثير من الكائنات والواجهات البرمجية المضمنة في لغة جافا سكريبت مثل المصفوفات Array والمكتبة Math. لاحظ أن الكائنات والواجهات البرمجية الأصلية أو المدمجة في جافا سكريبت لا تنشأ من تلقاء نفسها بل عليك إنشاؤها بنفسك في كل مرة تحتاجها، مثل الواجهة البرمجية للتنبيهات Notifications API التي تسمح للمتصفحات الحديثة بإطلاق تنبيهات، حيث تتطلب هذه الواجهة منك أن تنشئ نسخة جديدة باستخدام الدالة البانية لكل تنبيه تريد إطلاقه. جرّب إدخال السطر التالي إلى طرفية جافا سكريبت: const myNotification = new Notification("Hello!"); الخلاصة لقد أنهينا هذه المقال التي يمهّد لاستخدام الكائنات في جافا سكريبت، ولا بد أنك امتلكت بقراءته فكرة عن عمل الكائنات، بما في ذلك إنشاء كائنات بسيطة. ومن المهم إدراك أهمية الكائنات كبنى لتخزين البيانات والوظائف المترابطة. فلو حاولت تتبع جميع الخاصيات والتوابع في الكائن person الذي بنيناه في مثالنا شكل متغيرات ودوال منفصلة ستجد أنها طريقة غير مجدية ومحبطة، وستزيد مخاطر التضارب بين المتغيرات والدوال التي تمتلك نفس اﻷسماء. إذ تساعد الكائنات في حفظ المعلومات ضمن حاويات خاصة بها لتقليل مثل هذه المخاطر. ترجمة -وبتصرف- للمقال JavaScript object basics اقرأ أيضًا المقال السابق: مدخل إلى اﻷحداث في جافاسكريبت مدخل إلى جافاسكريبت كائنية التوجه (Object-Oriented JavaScript) لغة البرمجة بالكائنات Object-Oriented Programming برمجة الكائنات Objects في جافاسكريبت مختصر البرمجة كائنية التوجه OOP وتطبيقها في بايثون
    1 نقطة
  31. ربما كوّنت فكرة بعد قراءتك للمقالات السابقة حول أساسيات جافا سكريبت عما يمكن لهذه اللغة فعله، وكيفية استعمالها مع بقية تقنيات الويب، وكيف تبدو ميزاتها من منظور عام. لهذا نحاول في هذا المقال الاقتراب قليلًا من اﻷساسيات ونتعلم المزيد حول العمل مع المتغيرات وهي الكتل البرمجية اﻷبسط في جافا سكريبت. ننصحك قبل المتابعة في قراءة هذا المقال بالاطلاع على بعض المقالات السابقة مثل: أساسيات علوم الحاسوب. أساسيات HTML. أساسيات عمل CSS. الأدوات التي تحتاجها سنطلب إليك مع تقدم مقالنا كتابة بعض أسطر الشيفرة لنختر فهمك لما شرحناه. فإن كنت تستخدم متصفح حاسوب مكتبي، ستجد أن أفضل مكان لكتابة الشيفرة هو طرفية جافا سكريبت في المتصفح Web Console التي تمكّنك من التفاعل مع صفحة الويب عن طريق تنفيذ تعبيرات جافا سكريبت في سياق الصفحة (اضغط اﻷزرار "Ctrl" + "Shift" + "K" معًا لفتحها في متصفح فايرفوكس). المتغيّرات في جافا سكريبت يُعرّف المتغير بأنه حاوية تضم قيمة قد تكون عددًا يمكن أن نستخدمه لاحقًا في عملية جمع، أو سلسلة نصية يمكن أن نستخدمها كجزء من جملة. أمثلة عن المتغيرات لنلق نظرة على هذا المثال البسيط: <button id="button_A">Press me</button> <h3 id="heading_A"></h3> const buttonA = document.querySelector("#button_A"); const headingA = document.querySelector("#heading_A"); buttonA.onclick = () => { const name = prompt("What is your name?"); alert(`Hello ${name}, nice to see you!`); headingA.textContent = `Welcome ${name}`; }; See the Pen js-variables 1 by Hsoub Academy (@HsoubAcademy) on CodePen. عند النقر على الزر في هذا المثال سينفذ المتصفح بعض الشيفرة. إذ يعرض السطر اﻷول صندوقًا على الشاشة يطلب من المستخدم إدخال اسمه ومن ثم يخزّن الاسم كقيمة ضمن متغيّر. ويعرض السطر الثاني رسالة ترحيب تتضمن اسم المستخدم وقد أُخذ من المتغيّر في السطر السابق. أما السطر الثالث فيعرض الاسم على الصفحة. كيف سيكون الوضع دون متغيّرات؟ لكي نفهم الفائدة الكبيرة من استخدام المتغيرات، دعونا نفكّر بطريقة لكتابة شيفرة المثال السابق دون استعمال المتغيرات. سينتهي بنا اﻷمر إلى شيفرة من هذا القبيل: <button id="button_B">Press me</button> <h3 id="heading_B"></h3> const buttonB = document.querySelector("#button_B"); const headingB = document.querySelector("#heading_B"); buttonB.onclick = () => { alert(`Hello ${prompt("What is your name?")}, nice to see you!`); headingB.textContent = `Welcome ${prompt("What is your name?")}`; }; See the Pen js-variables 2 by Hsoub Academy (@HsoubAcademy) on CodePen. ربما لن تدرك جيدًا الصياغة التي استخدمناها حاليًا، لكن لا بد وأن تكون قد استوعبت الفكرة. فإن لم يكن لديك متغيرات، ستسأل المستخدم كل مرة عن اسمه إن احتجته في الشيفرة. إذًا من المنطقي استخدام المتغيرات، وستألفها مع تقدمك في تعلم جافا سكريبت. ومن المهم أن تعرف أنك قادر على تخزين أي شيء تقريبًا في المتغيرات وليس فقط النصوص والأرقام. فقد تضم المتغيرات بنى مركّبة من البيانات وحتى دالة بأكملها، وهذا ما ستتعلمه خلال تعلم لغة جافا سكريبت. ملاحظة: لقد أشرنا أن المتغيرات تضم قيمًا أي أن المتغيرات ليست قيمًا بحد ذاتها بل حاويات للقيم. يمكن أن تشبهها بعلبة من الكرتون تضع اﻷغراض بداخلها. التصريح عن المتغيرات لا بد من إنشاء المتغير قبل استخدامه، ندعو هذه العملية "تصريحًا عن المتغيّر". وكي نفعل ذلك في جافا سكريبت، نكتب الكلمة let يليها الاسم الذي تريده للمتغير كما يلي: let myName; let myAge; أنشأنا في الشيفرة السابقة متغيرين وأسميناهما myName و myAge. جرّب أن تكتب هذين السطرين في طرفية المتصفح ثم صرّح عن متغير أو أكثر وسمِّهما بالاسم الذي تريده. ملاحظة: يجب أن تنتهي جميع التعليمات في جافا سكريبت بفاصلة منقوطة (;)، فقد تعمل شيفرتك إن أهملتها سطرًا واحدًا لكنها لن تعمل إن حاولت كتابة عدة أسطر من الشيفرة دونها. لهذا تعود على استخدامها في نهاية كل تعليمة. بإمكانك اختبار وجود المتغيّر في بيئة التنفيذ أم لا بكتابة اسمه: myName; myAge; لا قيم حاليًا للمتغيرين السابقين، بل يمثلان حاويتان فارغتان. وعندما تضغط الزر "Enter" في الطرفية ستحصل على النتيجة undefined، لكن إن لم يكن المتغير موجودًا فستحصل على رسالة خطأ. جرّب أن تكتب: name; ملاحظة: لا تخلط بين متغيّر مصرّح عنه ولم تُسند له قيمة، ومتغير غير موجود أصلًا فهما أمران مختلفان تمامًا. فلو عدنا لمثال الصندوق، سيكون عدم وجود المتغير عدم وجود الصندوق، أما التصريح عن المتغير وعدم إسناد قيمة له فيعني أن الصندوق موجود لكنه فارغ. تهيئة المتغيّر حالما تصرح عن المتغير يمكنك تهيئته بإسناد قيمة له. نفّذ ذلك بكتابة اسم المتغيّر تليه إشارة المساواة (=) ثم القيمة التي تريدها. إليك مثالًا: myName = "Chris"; myAge = 37; جرّب أن تعود إلى طرفية المتصفح واكتب الشيفرة السابقة، ومن المفترض أن ترى بعدها كيف تعيد الطرفية القيمة التي أسندتها إلى المتغير. ونذكرّك بإمكانية عرض قيمة المتغير بمجرد كتابة اسمه في الطرفية. جرّب مجددًا الشيفرة التالية: myName; myAge; باﻹمكان أيضًا التصريح عن المتغير وتهيئته في نفس الوقت كالتالي: let myDog = "Rover"; وهذا ما ستفعله غالبًا لأنها طريقة أسرع. ملاحظة حول المتغيرات قد تصادف أيضًا طريقة مختلفة في التصريح عن المتغيرات وذلك باستخدام التعليمة var كما يلي: var myName; var myAge; لقد كانت هذه الطريقة هي الطريقة الوحيدة للتصريح عن المتغيرات في بدايات جافا سكريبت، وقد وجدت أنها طريقة مربكة أثناء الممارسة لهذا استبدلت لاحقًا بالتعليمة letفي النسخ الأحدث من جافا سكريبت، وهي تعليمة ﻹنشاء المتغيرات بشكل مختلف نوعًا ما عن var وتحل بعض المشاكل التي نتجت عنها. سنشرح تاليًا بعض نقاط الاختلاف بين التعليمتين لكننا لن نخوض بها جميعًا في الوقت الراهن، بل ستكتشف ذلك أثناء تقدمك في تعلم جافا سكريبت. لو كتبنا برنامج جافا سكريبت مكوّن من عدة أسطر تصرّح وتهيئ متغيرًا، بإمكانك استخدام التعليمة var للتصريح عن المتغيّر حتى بعد تهيئته وسيعمل! إليك مثالًا: myName = "Chris"; //تصريح وتهيئة متحول function logName() { console.log(myName); } logName(); var myName; //التصريح عن نفس المتحول من جديد ملاحظة: لن يعمل هذا المثال إن كتبت اﻷسطر السابقة سطرًا سطرًا في الطرفية، بل فقط إن نفذتها معًا في صفحة ويب. تعمل الشيفرة السابقة بسبب عملية تقديم أو رفع الكائن hoisting، لكنها لن تنفع مع التعليمة let. جرّب تبديل var بالتعليمة let في الشيفرة السابقة وستخفق العملية مع رسالة خطأ، وهذا أمر جيد، لأن تصريح متغير بعد تهيئته سابقًا مربك كثيرًا ويولد شيفرة صعبة الفهم. ومن ناحية ثانية، يمكن التصريح عن المتحول نفسه عدة مرات باستخدام var لكنك لن تستطيع ذلك مع let.ستعمل مثلًا الشيفرة التالية: var myName = "Chris"; var myName = "Bob"; لكن الشيفرة التالية ستعطي خطأً في السطر الثاني: let myName = "Chris"; let myName = "Bob"; وعليك أن تعيد كتابة الشيفرة لتصبح بالشكل: let myName = "Chris"; myName = "Bob"; ونؤكد أن وجود letهو قرار لغوي معقول، فلا معنى لتعريف المتغيرات مرة أخرى لأنها تربك القارئ. لهذه اﻷسباب وغيرها ننصحك باستخدام let في الشيفرة إلا إن كنت ستكتب صراحة شيفرة تدعم المتصفحات القديمة لأن جميع المتصفحات الحديثة تدعمها منذ عام 2015. ملاحظة: إن كنت ستجرّب الشيفرة التالية ضمن طرفية المتصفح فانسخها والصقها ككتلة واحدة. وفي متصفح كروم هنالك ميزة تسمح لك بإعادة تصريح المتغيرات باستخدام let وconst. > let myName = "Chris"; let myName = "Bob"; // SyntaxError: Identifier 'myName' has already been declared إن أدخلت الشيفرة سطرًا سطرًا: ستحصل على الخطأ > let myName = "Chris"; > let myName = "Bob"; // As two inputs: both succeed إن أدخلتهما معًا ستنجح العملية تحديث متغيّر بمجرّد أن تهيئ المتغير يمكنك تغيير قيمته مجددًا (تحديثها) بإسناد قيمة أخرى له. جرّب إدخال الأسطر التالية في طرفية المتصفح: Name = "Bob"; myAge = 40; نظرة إلى قواعد تسمية المتغيرات يمكنك أن تسمي متغيرك بأي اسم تريد مع وجود بعض القيود. وعمومًا التزم باستخدام المحارف اللاتينية (0-9, a-z, A-Z) ومحرف الشرطة السفلية (_). لا تستخدم محارف أخرى لأنها قد تسبب أخطاءً أو تجعل الشيفرة صعبة الفهم للقارئين حول العالم. لا تستخدم الشرطة السفلية في بداية اسم المتغيّر لأنه أسلوب مستخدم في بعض بنى جافا سكريبت وله دلالة خاصة. لا تستخدم أرقامًا في بداية الاسم، فهذا غير مسموح ويسبب خطأ. من العادات الآمنة أن تلتزم بحرف صغير في بداية الاسم، وإن أردت ضم عدة كلمات لتعيين اسم المتغير اكتب أحرف الكلمة اﻷولى جمعها بأحرف صغيرة ثم اجعل بدايات الكلمات التالية بأحرف كبيرة. وهذا ما استخدمناه في مقالنا حتى اﻵن. اجعل أسماء المتغيرات واضحة وتصف البيانات التي تخزّنها، ولا تستخدم أحرفًا مفردة أو عبارات طويلة. انتبه إلى أن المتغيرات حساسة لحالة اﻷحرف فالمتغير myAge مختلف عن myage. نقطة أخيرة: تجنب استخدام كلمات جافا سكريبت المحجوزة (التعليمات) كأسماء متغيرات مثل var و function و letو for، فلن يميزها المتصفح كمتغيرات وستظهر اﻷخطاء مباشرة. ملاحظة: إليك قائمة بالكلمات المحجوزة التي لا ينبغي استخدامها كأسماء متغيرات. وإليك بعض اﻷمثلة عن التسمية الجيدة للمتغيرات: age myAge init initialColor finalOutputValue audio1 audio2 وأمثلة عن التسمية السيئة: 1 a _12 myage MYAGE var Document skjfndskjfnbdskjfb thisisareallylongvariablenameman جرّب أن تسمي بعض المتغيرات وفقًا للنقاط التي ناقشناها سابقًا. أنواع المتغيرات توجد عدة أنواع للبيانات التي يمكن أن نخزنها ضمن المتغيرات، وسنناقشها باختصار في هذا القسم ونتعمق بها في مقالات لاحقة. لهذا سنلقي نظرة على أول نوعين. اﻷعداد بإمكانك تخزين اﻷعداد ضمن المتغيرات كاﻷعداد الصحيحة مثل (30) أو الأعداد العشرية مثل (2.234) وتُدعى أيضًا (أعداد عائمة float أو أعداد ذات فاصلة عائمة). ولا حاجة للتصريح عن نوع المتغير في جافا سكريبت على عكس العديد من لغات البرمجة اﻷخرى. وعندما تُخزّن أعدادًا ضمن المتغير لا داعي لإحاطة العدد بعلامتي تنصيص. let myAge = 17; النصوص (السلاسل النصية) السلاسل النصية هي مقاطع من نصوص، وعندما تخزّنها ضمن متغيّر لا بد من إحاطتها بعلامتي تنصيص مفردتين '' أو مزدوجتين "". فإن لم تفعل ذلك، تحاول جافا سكريبت تفسيرها كأسماء لمتغيرات أخرى. let dolphinGoodbye = "So long and thanks for all the fish"; القيم المنطقية وهي إحدى القيمتين true أو false( صحيح أو خاطئ). وتستخدمان عادة في اختبار تحقق شرط ما، ثم تنفيذ شيفرة بناءً على نتيجة الشرط. إليك مثالًا: let iAmAlive = true; لكن ما ستراه في الواقع شيفرة كهذه: let test = 6 < 3; وقد استخدم العامل (<) لاختبار إن كان الرقم 6 أصغر من 3 ثم خُزنت النتيجة false في المتغيّر. سترى ذلك بتفاصيل أكثر لاحقًا. المصفوفات تُعرّف المصفوفة بأنها كائن في جافا سكريبت يضم عدة قيم تفصل بينها فاصلة , ضمن قوسين مرّبعين []. جرّب إدخال الأسطر التالية في الطرفية: let myNameArray = ["Chris", "Bob", "Jim"]; let myNumberArray = [10, 15, 40]; بمجرّد أن تعرّف المصفوفات، تستطيع الوصول إلى أي قيمة من القيم المخزنة ضمنها باﻹشارة إلى موقعها. جرّب ما يلي: myNameArray[0]; //'Chris' تعيد myNumberArray[2]; // 40 تعيد تحدد اﻷقواس المربعة بعد اسم المصفوفة ترتيب القيمة الموافق لموقعها في المصفوفة، وانتبه إلى أن المصفوفات في جافا سكريبت تبدأ من الصفر. الكائنات تمثل الكائنات في لغات البرمجة بنية من الشيفرة تنمذج شيئًا في الواقع. فقد تنمذج كائنًا بسيطًا مثل صندوق يتضمن معلومات مثل طوله وعرضه وارتفاعه، أو قد يمثل الكائن شخصًا ويتضمن اسمه وطوله ووزنه واللغات التي يتكلمها وكيف ستقول "مرحبًا" له وهكذا. جرّب الشيفرة التالية في الطرفية: let dog = { name: "Spot", breed: "Dalmatian" }; وكي تسترجع المعلومات المخزنة في كائن، يمكنك استخدام الصياغة التالية: dog.name; لن نشرح أكثر عن الكائنات هنا، بل سنترك اﻷمر لمقالات أخرى. التحديد التلقائي للنوع تُحدد جافا سكريبت النوع تلقائيًا dynamically typed language ويعني ذلك أنك لن تحتاج إلى تحديد نوع البيانات التي تخزنها (أعداد، سلاسل نصية، مصفوفات) في متغير على عكس لغات أخرى. فإن صرحت عن متغير وأسندت إليه قيمة ضمن إشارتي تنصيص سيفهم المتصفح أن المتغير هو سلسلة نصية. let myString = "Hello"; وحتى لو كان ما داخل إشارتي التنصيص مجرد أرقام سيبقى نوع المتغير نصيًا فانتبه إلى ذلك: let myNumber = "500"; // المتغير من النوع النصي هنا typeof myNumber; myNumber = 500; // اﻵن يصبح المتغير عددًا typeof myNumber; جرّب أن تدخل الأسطر اﻷربعة السابقة في الطرفية سطرًا تلو اﻵخر وراقب النتيجة. لاحظ أننا نستخدم عامل خاص هو typeofيعيد نوع المتغيّر الذي تذكره بعده. فعندما استُدعي لأول مرة أعاد القيمة string لأن المتغير myNumber حتى لحظة كتابته كان نصيًا، لكن عندما استدعيته في المرة الثانية إعادة القيمة number. الثوابت في جافا سكريبت يمكن التصريح عن الثوابت constants في جافا سكريبت كما تصرّح عن المتغيرات لكن باستخدام التعليمة const مع بعض الاستثناءات: عليك تهيئة الثابت عندما تعرّفه. لا يمكن أن تسند لها قيمة أخرى بعد تهيئتها. إذ يمكنك مثلًا التصريح عن المتغير باستخدام letدون أن تهيئه: let count; لكن إن حاولت أن تفعل ذلك باستخدام const سترى رسالة خطأ: const count; يمكنك بعد التصريح عن متغير باستخدام let أن تهيئه في خطوة منفصلة (تُدعى بعملية إعادة اﻹسناد re-assigning): let count = 1; count = 2; لكن إن حاولت ذلك عند استخدام const سترى رسالة خطأ أيضًا: const count = 1; count = 2; وعلى الرغم من أن الثوابت في جافا سكريبت تشير دائمًا إلى نفس القيمة إلا أنه يمكن تغيير محتوى هذه الثوابت في بعض اﻷنواع مثل الكائنات. إليك مثالًا: const bird = { species: "Kestrel" }; console.log(bird.species); // "Kestrel" بإمكانك تحديث أو إضافة أو إزالة خاصيات من كائن حتى لو كان مصرّحًا عنه باستخدام const، فحتى لو تغير المحتوى في هذه الحالة، فسوف يشير الثابت دائمًا إلى نفس الكائن. bird.species = "Striated Caracara"; console.log(bird.species); // "Striated Caracara" متى نستخدم الثوابت والمتغيرات؟ لماذا نستخدم const إن لم تكن تفعل الكثير موازنة بالتعليمة let؟ لأن الواقع يقول أنها ذات فائدة كبيرة. فلو اطلع أي قارئ على شيفرة عُرّف فيها ثابت باستخدام const سيعرف بالتأكيد أن هذه القيمة لن تتغير لاحقًا وسيرتبط اسم هذا الثابت بقيمة ثابتة دائمًا. نتبنى في سلسلة مقالاتنا القاعدة التالية بخصوص let و const وهي كالتالي: استخدم const عندما تستطيع و let عندما يجب عليك ذلك. أي إن كنت تستطيع إسناد قيمة للمتغير عند التصريح عنه ولن تحتاج لتغييرها فصرّح عنه كثابت وإلا صرّح عنه كمتغير. الخلاصة تعرفنا في هذا المقال على المتغيرات والثوابت في لغة جافا سكريبت وأصبحت تمتلك معرفة لا بأس بها حول إنشائها واستخدامها، وسنكمل في مقالات أخرى تفصيل أنواع هذه المتغيرات وطرق استخدامها والتعامل معها. ترجمة -وبتصرف- لمقال Storing the information you need-Variables اقرأ أيضًا المقال السابق: الدوال وإعادة استخدام الشيفرة في جافا سكريبت تجربتك اﻷولى مع جافا سكريبت تعلم لغة جافا سكريبت من الصفر حتى الاحتراف أساسيات لغة جافاسكربت
    1 نقطة
  32. المُزخرفات من أعظم مميزات لغة بايثون، إذ تساعدك على بناء برنامجك باحترافية أكثر موفرة طريقة بسيطة لإضافة خاصيات جديدة للدالة. وهي ببساطة دوال تستطيع أن تعدل على دوال أخرى. تذكير ببعض المفاهيم الأساسية إذا لم تكن تعرف شيئا عن الدوال في لغة بايثون فيجب عليك العودة للدرس السابق الدوال في بايثون قبل أن تكمل قراءة هذا الدرس. تُعتبر الدوال في لغة بايثون كائنات من نوع الفئة الأولى أو First class objects. ما يعني أنّنا نستطيع القيام بالعديد من العمليات، وهي كالتالي: يُمكنك تعريف دالة داخل دالة أخرى يُمكنك أن تستدعي دالة داخل أخرى يُمكنك أن تقوم بتمرير دالة كمُعامل لدالة أخرى يُمكنك أن تُسند دالة لمُتغير يُمكنك إرجاع دالة داخل دالة أخرى بما أنّ المُزخرفات مُجرّد دوال فعلينا أن نبدأ من الأساس، لاحظ الدالة التالية: def say_hello(): print 'Hello!' عند استدعاء الدالة ستُطبع القيمة Hello على الشاشة، هذا ليس بالأمر المُعقد، الآن ماذا لو أردنا أن نعدل الدالة في جزء آخر من البرنامج لكي تطبع أشياء أخرى وتؤدي أغراضا أخرى قبل استدعاء الدالة أو بعد ذلك؟ يُمكن أن نعدّل الدالة مُباشرة، لكن هذا الأمر سيغير من طريقة سير البرنامج، إذ نريد أن نعدل الدالة في منطقة واحدة فقط من البرنامج وليس في كامل البرنامج، هذه المسألة تُحل بالمُزخرفات، وكما يدل اسمها فهي دوال تُزيّن وتُزخرف الدالة الأصلية، أي تُضيف عليها مهاما أخرى. سننشئ لهذه الدالة الآن مُزخرفا Decorator يقوم بطباعة Before قبل تنفيذ الدالة و After بعد تنفيذ الدالة، وذلك دون تعديل الدالة مُباشرة. انظر المثال التالي: def decorator(function): def function_decorator(): print 'Before' function() print 'After' return function_decorator الشيفرة أعلاه عبارة عن دالة تقبل دالة أخرى (الدالة التي نرغب بزَخرَفَتِها أو تزيينها) كمُعامل وبعدها نقوم بإنشاء دالة داخل هذه الدالة لطباعة القيمة Before ثم استدعاء الدالة الأصلية (المُعامل) بعدها طباعة After وأخيرا إرجاع الدالة الجديدة (وهي نُسخة مزخرفة من الدالة الأصلية). بعدها يُمكننا أن نستخدم هذا المُزخرف لزخرفة أي دالة مهما كانت، انظر المثال التالي: # -*- coding: utf-8 -*- def decorator(function): # إنشاء الدالة المسؤولة عن الزخرفة def function_decorator(): # إنشاء الدالة التي ستكون نسخة مزخرفة من الدالة المُمرّرة في كمُعامل print 'Before' # طباعة جملة قبل تنفيذ الدالة function() # استدعاء الدالة print 'After' return function_decorator # إرجاع الدالة مُزَخْرَفَةً def say_hello(): # إنشاء دالة عادية print 'Hello!' say_hello = decorator(say_hello) # زخرفة الدالة say_hello() # استدعاء النُسخة المُزخرفة من الدالة توفر لنا لغة بايثون طريقة أكثر مرونة لزخرفة الدوال، وهي بوضع اسم المُزخرف مسبوقا بالحرف @ قبل تعريف الدالة. أي أنّ السّطر التالي: def say_hello(): print 'Hello!' say_hello = decorator(say_hello) # زخرفة الدالة يُمكن أن يكون كالتالي: @decorator def say_hello(): # إنشاء دالة عادية print 'Hello!' وبالتالي سنتمكن من زخرفة أي دالة نرغب بزخرفتها كالتالي: @decorator def say_hello(): print 'Hello!' @decorator def say_hi(): print 'Hi!' @decorator def say_name(): print 'Abdelhadi!' say_hello() say_hi() say_name() عند تنفيذ الشيفرة أعلاه ستكون المخرجات كالتالي: Before Hello! After Before Hi! After Before Abdelhadi! After مُلاحظة: إذا كانت للدالة معاملات فما عليك إلا استخدام args* التي سبق وتحدثنا عنها في الدرس السابق. # -*- coding: utf-8 -*- def decorator(function): # إنشاء الدالة المسؤولة عن الزخرفة def function_decorator(*args): # إنشاء الدالة التي ستكون نسخة مزخرفة من الدالة المُمرّرة كمُعامل print 'Before' # طباعة جملة قبل تنفيذ الدالة function(*args) # استدعاء الدالة print 'After' return function_decorator # إرجاع الدالة مُزَخْرَفَةً لاحظ الدالتين function_decorator و function. أمثلة على المزخرفات في لغة بايثون إذا فهمت مبدأ المزخرفات فستستطيع أن تتعامل مع الدوال بمرونة عالية، وإليك بعض الأمثلة لاستخدام المُزخرفات لتأدية بعض المهام البسيطة: حساب مدة تنفيذ دالة إذا فهمت جيدا مبدأ المُزخرفات فستلاحظ بأنّك تستطيع تنفيذ مهام قبل تنفيذ الدالة ومهام بعد تنفيذها، ومما سبق نستنتج بأنّنا نستطيع أن نقوم بحفظ الوقت الحالي في مُتغير ثم تنفيذ الدالة وبعدها نقوم بحساب الفرق بين الوقت السابق والوقت الحالي، ما سيُرجع المُدة المُستغرقة لتنفيذ الدالة. البرنامج التالي مثال على مُزخرف لحساب مُدة دالة تطبع الجملة !Hello World مليون مرّة. # -*- coding: utf-8 -*- import time # جلب مكتبة الوقت لاستعمال دوال الوقت def function_time(function): def function_decorator(*args): start_time = time.time() # الحصول على وقت البداية function(*args) end_time = time.time() # الحصول على الوقت بعد نهاية التنفيذ # طباعة اسم الدالة والفرق بين وقت البداية ووقت النهاية print '%s function took %0.3f s' % (function.func_name, (end_time - start_time)) return function_decorator # إرجاع الدالة مُزَخْرَفَةً # زخرفة الدالة المسؤولة عن الطباعة مليون مرة @function_time def print_million_times(): for i in range(0, 1000000): print 'Hello World! 1,000,000 times!' print_million_times() البرنامج أعلاه سيطبع الجملة مليون مرة ثم يعرض الوقت المُستغرق لإنجاز العملية. الجملة الأخيرة ستكون شيئا كالتّالي: print_million_times function took 69.584 s ملاحظات: نستعمل التابع func_name للحصول على اسم الدالة المُمررة كمعامل، ويكون على شكل سلسلة نصية. نستعمل الجملة time.time للحصول على الوقت بالثواني، عدد الثواني الذي تنتجه الجملة هو عدد الثواني الذي مرّ منذ سنة 1970. يُمكنك استعمال هذا المُزخرف مع أي دالة تريد فقط اكتب اسم المُزخرف مسبوقا بالحرف @ ثم عرف الدالة بعده، وستحصل على الوقت المُستغرق لتنفيذ الدالة. حساب عدد مرات استدعاء دالة يُمكننا أن نستخدم المُزخرفات للحصول على عدد المرات التي استدعيت فيها دالة ما في برنامج مُعيّن، بحيث يحمل متغير قيمة العدد صفر، وفي كل مرة تستدعى فيها الدالة، فإن المُتغير يحمل القيمة مع زيادة بالعدد واحد، انظر المثال التالي. # -*- coding: utf-8 -*- # متغير العد n = 0 # المُزخرف def call_times(function): def decorated(): function() # استدعاء الدالة global n # جعل مُتغير العدّ عالميا n += 1 # زيادة قيمة المُتغير print 'Function was called', n, 'times' # طباعة قيمة المُتغير return decorated @call_times # زخرفة الدالة def func(): # إنشاء الدالة print 'Hello!' # استدعاء الدالة func() func() func() func() مُخرجات البرنامج أعلاه ستكون كالتالي: Hello! Function was called 1 times Hello! Function was called 2 times Hello! Function was called 3 times Hello! Function was called 4 times يُمكنك إصلاح الجمل من الناحية اللغوية بإضافة بعض العبارات الشرطية للبرنامج. إنشاء مزخرف لتنفيذ دالة عند تحقق شرط معين فقط يُمكنك أن تستعمل دالة تسجيل الدخول التي قُمنا بإنشائها كمُزخرف للدوال التي تحتاج لأن يكون المُستخدم مُسجلا دخوله. مثلا لنقل بأنّنا نريد أن نعرض على المُستخدم عدة خيارات بعضها يحتاج إلى تسجيل دخول المُستخدم وبعضها لا. الخيارات كالتّالي: تسجيل مُستخدم جديد (تسجيل الدخول غير مطلوب) طباعة جملة عشر مرات ( تسجيل الدخول غير مطلوب) الحصول على الوقت الحالي ( تسجيل الدخول غير مطلوب) طباعة اسم المُستخدم (تسجيل الدخول مطلوب) رؤية معلومات الحساب (تسجيل الدخول مطلوب) تعديل كلمة المرور (تسجيل الدخول مطلوب) مبدأ عمل البرنامج سيكون كالتالي: إنشاء الدوال المسؤولة عن الخيارات عرض الخيارات على المُستخدم زخرفة الدوال التي تطلب تسجيل المُستخدم بمُزخرف تسجيل الدخول المُزخرف سيتحقق من أنّ المُستخدم قد سجل دخوله، إذا كان الأمر كذلك، تنفّذ الدالة وإذا لم يتحقق الشرط فلا تنفذ. لنقل بأنّ اسم مُزخرف التحقق من تسجيل الدخول هو is_user_logged_in، ستكون الدوال التي تطلب تسجيل الدخول مُزَخْرَفَةً كالتالي: @if_user_logged_in def account_info(): print 'Username:', username, 'Password:', password تمارين تمرين 1 أنشئ دالة للجمع بين عددين، وبعدها أنشئ مُزخرفا يقوم بمُضاعفة النتيجة. تمرين 2 أنشئ دالة للحصول على قيم من المُستخدم وقم بزخرفة لطباعة جملة ترحيب قبل استدعاء الدالة وجملة توديع بعد استدعاءها. تمرين 3 أكمل البرنامج الخاص بالمثال الثالث (إنشاء مُزخرف لتنفيذ دالة عند تحقق شرط مُعين فقط). تفاصيل التمرين موجودة بالمثال.
    1 نقطة
×
×
  • أضف...