كما نعلم من فصل أنواع البيانات، هناك ثمانية أنواع من البيانات في JavaScript. سبعة منها تسمى "بدائية"، لأن قيمها تحتوي على شيء واحد فقط (سواء كان سلسلة أو رقمًا أو أي شيء آخر).
في المقابل، يتم استخدام الكائنات لتخزين مجموعات المفاتيح من البيانات المختلفة والكيانات الأكثر تعقيدًا. في JavaScript، تخترق الكائنات كل جانب من جوانب اللغة تقريبًا. لذلك يجب علينا أن نفهمها أولاً قبل التعمق في أي مكان آخر.
يمكن إنشاء كائن بأقواس الشكل {…}
مع قائمة خصائص اختيارية. الخاصية هي زوج "مفتاح: قيمة"، حيث key
عبارة عن سلسلة (وتسمى أيضًا "اسم الخاصية")، value
يمكن أن تكون أي شيء.
يمكننا أن نتخيل كائنًا كخزانة بها ملفات موقعة. يتم تخزين كل جزء من البيانات في ملفه بواسطة المفتاح. من السهل العثور على ملف باسمه أو إضافة/إزالة ملف.
يمكن إنشاء كائن فارغ ("خزانة فارغة") باستخدام إحدى صيغتين:
السماح للمستخدم = كائن جديد ()؛ // بناء جملة "منشئ الكائن". دع المستخدم = {}؛ // بناء جملة "الكائن الحرفي".
عادة، يتم استخدام الأقواس المعقوفة {...}
. يسمى هذا الإعلان كائنًا حرفيًا .
يمكننا فورًا وضع بعض الخصائص في {...}
كأزواج "مفتاح: قيمة":
السماح للمستخدم = {// كائن الاسم: "جون"، // حسب مفتاح "الاسم" قيمة المتجر "جون" العمر: 30 // حسب قيمة مخزن "العمر" 30 };
تحتوي الخاصية على مفتاح (يُعرف أيضًا باسم "الاسم" أو "المعرف") قبل النقطتين ":"
وقيمة على يمينه.
في كائن user
، هناك خاصيتين:
الخاصية الأولى لها الاسم "name"
والقيمة "John"
.
والثاني يحمل اسم "age"
وقيمته 30
.
يمكن تخيل كائن user
الناتج كخزانة تحتوي على ملفين موقعين يحملان اسم "الاسم" و"العمر".
يمكننا إضافة الملفات وإزالتها وقراءتها منه في أي وقت.
يمكن الوصول إلى قيم الخاصية باستخدام تدوين النقطة:
// الحصول على قيم خصائص الكائن: تنبيه (اسم المستخدم) ؛ // جون تنبيه (user.age ); // 30
يمكن أن تكون القيمة من أي نوع. دعونا نضيف واحدة منطقية:
user.isAdmin = true;
لإزالة خاصية، يمكننا استخدام عامل delete
:
حذف user.age؛
يمكننا أيضًا استخدام أسماء خصائص متعددة الكلمات، ولكن بعد ذلك يجب أن يتم اقتباسها:
السماح للمستخدم = { الاسم: "جون"، العمر: 30, "يحب الطيور": صحيح // يجب أن يتم اقتباس اسم الخاصية متعدد الكلمات };
قد تنتهي الخاصية الأخيرة في القائمة بفاصلة:
السماح للمستخدم = { الاسم: "جون"، العمر: 30, }
وهذا ما يسمى بالفاصلة "زائدة" أو "معلقة". يجعل من السهل إضافة/إزالة/التنقل بين الخصائص، لأن جميع الخطوط تصبح متشابهة.
بالنسبة لخصائص الكلمات المتعددة، لا يعمل الوصول إلى النقطة:
// هذا من شأنه أن يعطي خطأ في بناء الجملة user.likes الطيور = صحيح
جافا سكريبت لا يفهم ذلك. يعتقد أننا نخاطب user.likes
، ثم يعطي خطأً في بناء الجملة عندما يصادف birds
غير متوقعة.
تتطلب النقطة أن يكون المفتاح معرفًا متغيرًا صالحًا. وهذا يعني: أنه لا يحتوي على مسافات، ولا يبدأ برقم، ولا يتضمن أحرفًا خاصة (يُسمح بـ $
_
).
هناك "تدوين قوس مربع" بديل يعمل مع أي سلسلة:
دع المستخدم = {}؛ // تعيين المستخدم["يحب الطيور"] = صحيح؛ // يحصل تنبيه (مستخدم ["يحب الطيور"])؛ // حقيقي // يمسح حذف المستخدم["يحب الطيور"]؛
الآن كل شيء على ما يرام. يرجى ملاحظة أن السلسلة الموجودة داخل الأقواس مقتبسة بشكل صحيح (أي نوع من علامات الاقتباس سيفي بالغرض).
توفر الأقواس المربعة أيضًا طريقة للحصول على اسم الخاصية كنتيجة لأي تعبير – بدلاً من سلسلة حرفية – مثل من متغير كما يلي:
Let key = "يحب الطيور"; // نفس المستخدم["يحب الطيور"] = صحيح؛ المستخدم [المفتاح] = صحيح؛
هنا، يمكن حساب key
المتغير في وقت التشغيل أو يعتمد على إدخال المستخدم. ومن ثم نستخدمه للوصول إلى العقار. وهذا يمنحنا قدرا كبيرا من المرونة.
على سبيل المثال:
السماح للمستخدم = { الاسم: "جون"، العمر: 30 }; Let key = موجه("ماذا تريد أن تعرف عن المستخدم؟", "name"); // الوصول عن طريق المتغير تنبيه (المستخدم [مفتاح])؛ // جون (إذا أدخلت "الاسم")
لا يمكن استخدام تدوين النقطة بطريقة مماثلة:
السماح للمستخدم = { الاسم: "جون"، العمر: 30 }; دع المفتاح = "الاسم"؛ تنبيه (user.key) // غير محدد
يمكننا استخدام الأقواس المربعة في كائن حرفي، عند إنشاء كائن. وهذا ما يسمى الخصائص المحسوبة .
على سبيل المثال:
Let Fruit = موجه ("أي فاكهة للشراء؟"، "Apple")؛ دع الحقيبة = { [الفاكهة]: 5، // اسم الخاصية مأخوذ من المتغير Fruit }; تنبيه(bag.apple); // 5 إذا كانت الفاكهة = "تفاحة"
معنى الخاصية المحسوبة بسيط: [fruit]
تعني أن اسم الخاصية يجب أن يؤخذ من fruit
.
فإذا أدخل الزائر "apple"
ستصبح bag
{apple: 5}
.
في الأساس، يعمل هذا بنفس الطريقة:
Let Fruit = موجه ("أي فاكهة للشراء؟"، "Apple")؛ دع الحقيبة = {}؛ // خذ اسم الخاصية من متغير الفاكهة كيس [فاكهة] = 5؛
…ولكن يبدو أجمل.
يمكننا استخدام تعبيرات أكثر تعقيدًا داخل الأقواس المربعة:
دع الفاكهة = 'تفاحة'؛ دع الحقيبة = { [الفاكهة + "أجهزة الكمبيوتر"]: 5 //bag.appleComputers = 5 };
الأقواس المربعة أقوى بكثير من التدوين النقطي. أنها تسمح بأي أسماء الممتلكات والمتغيرات. ولكنها أيضًا أكثر تعقيدًا في الكتابة.
لذا، في معظم الأحيان، عندما تكون أسماء الخصائص معروفة وبسيطة، يتم استخدام النقطة. وإذا أردنا شيئًا أكثر تعقيدًا، فإننا ننتقل إلى الأقواس المربعة.
في الكود الحقيقي، غالبًا ما نستخدم المتغيرات الموجودة كقيم لأسماء الخصائص.
على سبيل المثال:
وظيفة makeUser(الاسم، العمر) { يعود { الاسم: اسم، العمر : العمر , // ... خصائص أخرى }; } Let user = makeUser("John", 30); تنبيه (اسم المستخدم) ؛ // جون
في المثال أعلاه، الخصائص لها نفس أسماء المتغيرات. إن حالة الاستخدام الخاصة بإنشاء خاصية من متغير شائعة جدًا، حيث يوجد اختصار خاص لقيمة الخاصية لجعلها أقصر.
بدلًا من name:name
يمكننا كتابة name
، على النحو التالي:
وظيفة makeUser(الاسم، العمر) { يعود { الاسم، // نفس الاسم: الاسم العمر، // نفس العمر: العمر // ... }; }
يمكننا استخدام كل من الخصائص العادية والاختصارات في نفس الكائن:
السماح للمستخدم = { الاسم، // نفس الاسم: الاسم العمر: 30 };
كما نعلم بالفعل، لا يمكن أن يكون للمتغير اسم مساوٍ لإحدى الكلمات المحفوظة في اللغة مثل "for"، "let"، "return" وما إلى ذلك.
لكن بالنسبة لخاصية الكائن، لا يوجد مثل هذا القيد:
// هذه الخصائص صحيحة دع الكائن = { ل: 1، اسمحوا: 2، العودة: 3 }; تنبيه (obj.for + obj.let + obj.return ); // 6
باختصار، لا توجد قيود على أسماء العقارات. يمكن أن تكون أي سلاسل أو رموز (نوع خاص للمعرفات، سيتم تغطيته لاحقًا).
يتم تحويل الأنواع الأخرى تلقائيًا إلى سلاسل.
على سبيل المثال، يصبح الرقم 0
سلسلة نصية "0"
عند استخدامه كمفتاح خاصية:
دع الكائن = { 0: "اختبار" // نفس "0": "اختبار" }; // كلا التنبيهين يصلان إلى نفس الخاصية (يتم تحويل الرقم 0 إلى سلسلة "0") تنبيه (obj["0"] ); // امتحان تنبيه (obj[0])؛ // اختبار (نفس الخاصية)
هناك مشكلة بسيطة لها خاصية خاصة اسمها __proto__
. لا يمكننا تعيينها على قيمة غير كائن:
دع obj = {}; obj.__proto__ = 5; // تعيين رقم تنبيه(obj.__proto__); // [كائن كائن] - القيمة عبارة عن كائن، ولم تعمل على النحو المنشود
كما نرى من الكود، يتم تجاهل التعيين إلى الرقم 5
البدائي.
سنغطي الطبيعة الخاصة لـ __proto__
في الفصول اللاحقة، ونقترح طرقًا لإصلاح مثل هذا السلوك.
من الميزات البارزة للكائنات في JavaScript، مقارنة بالعديد من اللغات الأخرى، إمكانية الوصول إلى أي خاصية. لن يكون هناك خطأ إذا كانت الخاصية غير موجودة!
قراءة خاصية غير موجودة تؤدي فقط إلى إرجاع undefined
. لذلك يمكننا بسهولة اختبار ما إذا كانت الخاصية موجودة:
دع المستخدم = {}؛ تنبيه (user.noSuchProperty === غير محدد)؛ // صحيح يعني "لا يوجد مثل هذه الخاصية"
هناك أيضًا عامل تشغيل خاص "in"
لذلك.
بناء الجملة هو:
"المفتاح" في الكائن
على سبيل المثال:
Let user = { الاسم: "جون"، العمر: 30 }; تنبيه ("العمر" في المستخدم)؛ // صحيح، user.age موجود تنبيه ("blabla" في المستخدم)؛ // خطأ، user.blabla غير موجود
يرجى ملاحظة أنه على الجانب الأيسر يجب أن يكون in
اسم العقار . عادة ما تكون هذه سلسلة مقتبسة.
إذا حذفنا علامات الاقتباس، فهذا يعني أن المتغير يجب أن يحتوي على الاسم الفعلي المراد اختباره. على سبيل المثال:
دع المستخدم = { العمر: 30 }; دع المفتاح = "العمر"؛ تنبيه (مفتاح في المستخدم)؛ // صحيح، خاصية "العمر" موجودة
لماذا يوجد in
التشغيل؟ ألا يكفي المقارنة مع undefined
؟
حسنًا، في معظم الأحيان تكون المقارنة مع undefined
تعمل بشكل جيد. ولكن هناك حالة خاصة عندما تفشل، ولكن "in"
يعمل بشكل صحيح.
يحدث ذلك عندما توجد خاصية كائن، ولكنها تخزن undefined
:
دع الكائن = { الاختبار: غير محدد }; تنبيه (obj.test)؛ // إنها غير محددة، لذا - لا يوجد مثل هذه الخاصية؟ تنبيه ("اختبار" في الكائن)؛ // صحيح، الخاصية موجودة!
في الكود أعلاه، الخاصية obj.test
موجودة تقنيًا. لذا in
عامل التشغيل يعمل بشكل صحيح.
نادرًا ما تحدث مثل هذه المواقف، لأنه لا ينبغي تعيين undefined
صراحةً. نستخدم في الغالب null
للقيم "غير المعروفة" أو "الفارغة". لذا فإن in
التشغيل هو ضيف غريب في الكود.
للتجول فوق جميع مفاتيح الكائن، يوجد شكل خاص للحلقة: for..in
. وهذا شيء مختلف تمامًا عن البناء for(;;)
الذي درسناه من قبل.
بناء الجملة:
لـ (المفتاح في الكائن) { // ينفذ النص لكل مفتاح بين خصائص الكائن }
على سبيل المثال، لنخرج جميع خصائص user
:
السماح للمستخدم = { الاسم: "جون"، العمر: 30, المشرف: صحيح }; لـ (السماح بإدخال المستخدم) { // مفاتيح تنبيه (مفتاح)؛ // الاسم، العمر، isAdmin // قيم المفاتيح تنبيه (المستخدم [مفتاح])؛ // جون، 30، صحيح }
لاحظ أن جميع بنيات "for" تسمح لنا بالإعلان عن متغير التكرار داخل الحلقة، مثل let key
هنا.
يمكننا أيضًا استخدام اسم متغير آخر هنا بدلاً من key
. على سبيل المثال، يتم أيضًا استخدام "for (let prop in obj)"
على نطاق واسع.
هل الأشياء مرتبة؟ بمعنى آخر، إذا قمنا بالتكرار على كائن ما، فهل نحصل على جميع الخصائص بنفس ترتيب إضافتها؟ هل يمكننا الاعتماد على هذا؟
الإجابة المختصرة هي: "مرتبة بطريقة خاصة": يتم فرز خصائص الأعداد الصحيحة، وتظهر الخصائص الأخرى بترتيب الإنشاء. التفاصيل تتبع.
على سبيل المثال، دعونا نفكر في كائن يحتوي على رموز الهاتف:
دع الرموز = { "49": "ألمانيا"، "41": "سويسرا"، "44": "بريطانيا العظمى"، // ..، "1": "الولايات المتحدة الأمريكية" }; لـ (دع الكود في الرموز) { تنبيه (رمز)؛ // 1، 41، 44، 49 }
يمكن استخدام الكائن لاقتراح قائمة من الخيارات للمستخدم. إذا كنا ننشئ موقعًا مخصصًا بشكل أساسي للجمهور الألماني، فمن المحتمل أن يكون 49
هو الأول.
لكن إذا قمنا بتشغيل الكود، فسنرى صورة مختلفة تمامًا:
الولايات المتحدة الأمريكية (1) تتقدم أولاً
ثم سويسرا (41) وهكذا.
يتم ترتيب رموز الهاتف تصاعديًا، لأنها أعداد صحيحة. لذلك نرى 1, 41, 44, 49
.
خصائص عدد صحيح؟ ما هذا؟
مصطلح "خاصية عدد صحيح" هنا يعني سلسلة يمكن تحويلها من وإلى عدد صحيح دون تغيير.
لذلك، "49"
هو اسم خاصية عدد صحيح، لأنه عندما يتم تحويله إلى عدد صحيح والعودة، فإنه لا يزال كما هو. لكن "+49"
و "1.2"
ليسا كذلك:
// الرقم (...) يتحول بشكل صريح إلى رقم // Math.trunc هي دالة مضمنة تقوم بإزالة الجزء العشري تنبيه( سلسلة(Math.trunc(Number("49"))) ); // "49"، نفس خاصية العدد الصحيح تنبيه( سلسلة(Math.trunc(Number("+49"))) ); // "49"، ليست نفس "+49" ⇒ ليست خاصية عدد صحيح تنبيه( سلسلة(Math.trunc(Number("1.2"))) ); // "1"، وليس نفس "1.2" ⇒ ليست خاصية عدد صحيح
…ومن ناحية أخرى، إذا كانت المفاتيح غير صحيحة، فسيتم إدراجها في ترتيب الإنشاء، على سبيل المثال:
السماح للمستخدم = { الاسم: "جون"، اللقب: "سميث" }; عمر المستخدم = 25; // أضف واحدًا آخر // يتم إدراج الخصائص غير الصحيحة في ترتيب الإنشاء لـ (دع الدعامة في المستخدم) { تنبيه (دعامة)؛ // الاسم واللقب والعمر }
لذا، لإصلاح مشكلة رموز الهاتف، يمكننا "الغش" عن طريق جعل الرموز غير صحيحة. إن إضافة علامة الجمع "+"
قبل كل رمز يكفي.
مثله:
دع الرموز = { "+49": "ألمانيا"، "+41": "سويسرا", "+44": "بريطانيا العظمى"، // ..، "+1": "الولايات المتحدة الأمريكية" }; لـ (دع الكود في الرموز) { تنبيه(+رمز); // 49، 41، 44، 1 }
الآن يعمل على النحو المنشود.
الكائنات عبارة عن صفائف ترابطية لها العديد من الميزات الخاصة.
يقومون بتخزين الخصائص (أزواج القيمة الرئيسية)، حيث:
يجب أن تكون مفاتيح الخاصية عبارة عن سلاسل أو رموز (سلاسل عادةً).
يمكن أن تكون القيم من أي نوع.
للوصول إلى العقار، يمكننا استخدام:
تدوين النقطة: obj.property
.
تدوين الأقواس المربعة obj["property"]
. تسمح الأقواس المربعة بأخذ المفتاح من متغير، مثل obj[varWithKey]
.
عوامل تشغيل إضافية:
لحذف خاصية: delete obj.prop
.
للتحقق من وجود خاصية بالمفتاح المحدد: "key" in obj
.
للتكرار على كائن: حلقة for (let key in obj)
.
ما درسناه في هذا الفصل يسمى "كائن عادي"، أو مجرد Object
.
هناك العديد من الأنواع الأخرى من الكائنات في JavaScript:
Array
لتخزين مجموعات البيانات المطلوبة،
Date
لتخزين المعلومات حول التاريخ والوقت،
Error
لتخزين المعلومات حول خطأ.
…وهلم جرا.
لديهم ميزاتهم الخاصة التي سندرسها لاحقًا. في بعض الأحيان يقول الأشخاص شيئًا مثل "نوع المصفوفة" أو "نوع التاريخ"، لكنهم رسميًا ليسوا أنواعًا خاصة بهم، لكنهم ينتمون إلى نوع بيانات "كائن" واحد. ويقومون بتوسيعها بطرق مختلفة.
الكائنات في JavaScript قوية جدًا. هنا قمنا للتو بخدش سطح موضوع ضخم حقًا. سنعمل بشكل وثيق مع الكائنات ونتعلم المزيد عنها في أجزاء أخرى من البرنامج التعليمي.
الأهمية: 5
اكتب الكود، سطر واحد لكل إجراء:
إنشاء user
كائن فارغ.
أضف name
الخاصية بالقيمة John
.
أضف surname
الخاصية بالقيمة Smith
.
قم بتغيير قيمة name
إلى Pete
.
إزالة name
الخاصية من الكائن.
دع المستخدم = {}؛ user.name = "جون"; user.surname = "سميث"; user.name = "بيت"; حذف اسم المستخدم؛
الأهمية: 5
اكتب الدالة isEmpty(obj)
التي تُرجع true
إذا كان الكائن لا يحتوي على خصائص، false
إذا لم يكن له خصائص.
يجب أن تعمل مثل هذا:
دع الجدول الزمني = {}؛ تنبيه (isEmpty (جدول))؛ // حقيقي جدول["8:30"] = "انهض"; تنبيه (isEmpty (جدول زمني))؛ // خطأ شنيع
افتح صندوق الرمل مع الاختبارات.
ما عليك سوى التكرار فوق الكائن return false
على الفور إذا كان هناك خاصية واحدة على الأقل.
الوظيفة فارغة (obj) { لـ (دع المفتاح في obj) { // إذا بدأت الحلقة، فهناك خاصية عودة كاذبة. } عودة صحيحة؛ }
افتح الحل بالاختبارات في وضع الحماية.
الأهمية: 5
لدينا كائن يقوم بتخزين رواتب فريقنا:
دع الرواتب = { جون: 100، آن: 160، بيت: 130 }
اكتب الكود الخاص بجمع كل الرواتب وقم بتخزينه في المتغير sum
. ينبغي أن يكون 390
في المثال أعلاه.
إذا كانت salaries
فارغة فيجب أن تكون النتيجة 0
.
دع الرواتب = { جون: 100، آن: 160، بيت: 130 }; دع المبلغ = 0؛ لـ (دع المفتاح في الرواتب) { مجموع += الرواتب[مفتاح]; } تنبيه (مجموع)؛ // 390
الأهمية: 3
قم بإنشاء دالة multiplyNumeric(obj)
التي تقوم بضرب كافة قيم الخصائص الرقمية لـ obj
في 2
.
على سبيل المثال:
// قبل المكالمة السماح بالقائمة = { العرض: 200، الارتفاع: 300، العنوان: "قائمتي" }; multiplyNumeric(menu); // بعد المكالمة القائمة = { العرض: 400، الارتفاع: 600، العنوان: "قائمتي" };
يرجى ملاحظة أن multiplyNumeric
لا يحتاج إلى إرجاع أي شيء. يجب أن يقوم بتعديل الكائن في مكانه.
ملاحظة: استخدم typeof
للتحقق من وجود رقم هنا.
افتح صندوق الرمل مع الاختبارات.
وظيفة مضاعفة عددية (obj) { لـ (دع المفتاح في obj) { إذا (نوع الكائن[مفتاح] == 'رقم') { obj[مفتاح] *= 2; } } }
افتح الحل بالاختبارات في وضع الحماية.