في هذه المقالة ، قدم المؤلف ، وهو مطور أمامي ، نظرة عامة على الطرق الرئيسية لإنشاء وتعديل ومقارنة كائنات JavaScript.تعد الكائنات أحد المفاهيم الأساسية في JavaScript. عندما بدأت بدراستها ، بدت لي بسيطة جدًا: مجرد مفتاحين وقيم ، كما هو موضح في النظرية.
فقط بعد مرور بعض الوقت بدأت أدرك أن الموضوع أكثر تعقيدًا مما كنت أعتقد. ثم بدأت بدراسة المعلومات من مصادر مختلفة. قدم بعضهم فكرة جيدة عن الموضوع ، لكنني لم أستطع رؤية الصورة الكاملة على الفور.
في هذا المنشور ، حاولت تغطية جميع جوانب العمل مع كائنات في JS ، دون التعمق في التفاصيل الفردية ، ولكن دون فقدان التفاصيل المهمة التي ستساعدك على فهم الموضوع والشعور بمزيد من الثقة أثناء دراسته الإضافية.
فلنبدأ بالأساسيات.
كائن
الكائن في JavaScript هو ببساطة مجموعة من الخصائص ، كل منها عبارة عن زوج قيم مفتاح. يمكن الوصول إلى المفاتيح باستخدام
الترقيم المنقط (
obj.a ) أو بين قوسين (
obj ['a'] ).
تذكر أنه يجب استخدام الأقواس إذا كان المفتاح:
- ليس معرّف جافا سكريبت صالحًا (يحتوي على مسافة وشرطة ويبدأ برقم ...)
- متغير.
إحدى الخصائص التي تحصل عليها الكائنات في JS عند إنشائها تسمى
Prototype ، وهذا مفهوم مهم جدًا.
النموذج الأولي
كل كائن في JavaScript له خاصية داخلية تسمى
Prototype . في معظم المتصفحات ، يمكنك الرجوع إليها بالتعيين
__proto__ .
النموذج الأولي هو طريقة لتوفير وراثة الملكية في JavaScript. لذا يمكنك مشاركة الوظائف دون تكرار التعليمات البرمجية في الذاكرة. تعمل الطريقة عن طريق إنشاء علاقة بين كائنين.
ببساطة ، يقوم النموذج الأولي بإنشاء مؤشر من كائن إلى آخر.
سلسلة النموذج الأوليفي كل مرة يبحث فيها JS عن خاصية في الكائن ولا يجدها مباشرة في الكائن نفسه ، فإنه يتحقق من وجود الخاصية في كائن النموذج الأولي. إذا لم يكن هناك خاصية فيه ، فسيستمر JS في البحث في النموذج الأولي للكائن ذي الصلة. سيستمر هذا حتى يجد JS خاصية مناسبة أو يصل إلى نهاية السلسلة.
دعونا نلقي نظرة على مثال:
var cons = function () { this.a = 1; this.b = 2; } var obj = new cons(); </i> cons.prototype.b = 3; cons.prototype.c = 4;
السلبيات هي مُنشئ (مجرد وظيفة يمكن استدعاؤها باستخدام عامل التشغيل
الجديد ).
في السطر الخامس ، نقوم بإنشاء كائن جديد - نسخة جديدة من
السلبيات . مباشرة بعد الإنشاء ، يحصل
obj أيضًا على خاصية نموذج أولي.
والآن نضيف خصائص (
'b'، 'c' ) إلى النموذج الأولي للكائن
السلبي .
ضع في اعتبارك
الهدف :
obj.a // 1 - كل شيء كما كان من
قبل ،
obj.a لا يزال 1.
obj.c -
obj ليس
لديه خاصية
c ! ومع ذلك ، كما ذكرنا سابقًا ، سيبحث JS عنه الآن في النموذج الأولي
ويعيد قيمة 4.
الآن دعونا نفكر في ما هي قيمة
obj.b وماذا ستصبح عندما نزيل
obj.b ؟
Obj.b هو 2. لقد قمنا بتعيين الخاصية
b ، لكننا قمنا بذلك من أجل النموذج الأولي ، لذلك عندما نتحقق من
obj.b ، ما زلنا نحصل على 2. ومع ذلك ، فور حذف
obj.b ، لن يكون JS قادرًا على العثور على
b في o
bj وبالتالي ستواصل البحث في النموذج الأولي وترجع القيمة 3.
بعد ذلك ، أريد أن أتحدث بإيجاز عن طرق مختلفة لإنشاء كائن والمزيد عن النماذج الأولية.
إنشاء كائن
حرفيا الكائن: let obj = {a: 1}؛أنشأنا كائنًا بسلسلة النموذج الأولي التالية:
obj ---> Object.prototype ---> nullكما يمكنك أن تخمن ، فإن
object.prototype هو النموذج الأولي للكائن ، وكذلك نهاية سلسلة النموذج الأولي.
Object.create (): var newObj = Object.create (obj)؛سيكون لدى
NewObj سلسلة النموذج الأولي التالية:
newObj ---> obj ---> Object.prototype ---> nullمُنشئ. كما في المثال أعلاه ، فإن المنشئ هو مجرد وظيفة JS تسمح لنا باستخدام عامل التشغيل الجديد لإنشاء مثيلات جديدة منه.
فصول ES6: class rectangle { constructor(height, width) { this.height = height; this.width = width; } getArea() { return this.height * this.width; } } let square = new rectangle(2, 2);
المربع عبارة عن مثيل من مُنشئ
المستطيل ، ولذا يمكننا استدعاء
square.getArea () // 4 و
square.width ، بالإضافة إلى جميع الوظائف الموروثة من
object.prototype .
ما هي الطريقة الأفضل؟ إذا كنت تخطط لإنشاء مثيلات متعددة ، يمكنك استخدام ES6 أو المُنشئ. إذا كنت تخطط لإنشاء كائن مرة واحدة ، فمن الأفضل تحديد حرفي ، لأن هذه هي أسهل طريقة.
والآن ، عندما تعلمنا عن
النموذج الأولي وتعرفنا على جميع طرق إنشاء كائنات جديدة ، يمكننا المضي قدمًا لمناقشة أحد أكثر الجوانب المربكة المرتبطة بالأشياء.
مقارنة وتعديل الكائنات
في JavaScript ، تكون الكائنات من النوع المرجعيعندما نقوم بإنشاء كائن ،
دع obj = {a: 1} ؛ ، يحصل الكائن المتغير على العنوان في ذاكرة الكائن ، ولكن ليس قيمته! من الضروري فهم هذا الاختلاف ، حيث قد تحدث أخطاء خلاف ذلك. عندما نقوم بإنشاء كائن آخر ،
دعنا newObj = obj ، نقوم في الواقع بإنشاء
مؤشر لمنطقة معينة من كائن الذاكرة ، وليس كائنًا جديدًا تمامًا.
هذا يعني أنه من خلال تنفيذ
newObj.a = 2 ، فإننا في الواقع نغير
obj بحيث يصبح
oba.a 2!
يؤدي هذا النهج بسهولة إلى ظهور الأخطاء ، لذلك تعمل العديد من الشركات مع أشياء ثابتة. بدلاً من تغيير كائن تم إنشاؤه بالفعل ، سيتعين عليك مرة أخرى إنشاء كائن جديد (نسخة من الأصل) وإجراء تغييرات عليه بالفعل. هذه هي الطريقة التي تعمل بها المكتبات المهمة مثل Redux ، وعمومًا يعد هذا أحد المفاهيم الأساسية للبرمجة الوظيفية. اقرأ المزيد
هنا .
المساواةمما سبق ، يتبع ذلك أيضًا أن شيئين لا يمكن أن يكونا متساويين أبدًا ، حتى لو كان لديهم نفس الخصائص. هذا يرجع إلى حقيقة أن JS في الواقع يقارن موقع الكائنات في الذاكرة ، ولا يوجد شيئان في نفس خلية الذاكرة.
لذا ، من المحتمل أنك تساءلت بالفعل عن كيفية مقارنة الأشياء أو كيفية إجراء معالجات مختلفة مع الكائنات ، بالنظر إلى شرط ثباتها.
فكر في بعض الاحتمالات.
تغيير الكائنافترض أنه من الواضح أنه لا يجب تغيير الكائنات بطريقة جيدة ، لذلك نريد إنشاء نسخة من الكائن المقابل وتغيير خصائصه. يأتي
Object.assign () إلى
الإنقاذ .
var obj = { a : 1, b : 2}; var newObj = Object.assign({}, obj,{a:2})
إذا أردنا تغيير قيمة خاصية
الكائن ، فيمكننا استخدام
الكائن. تعيين لإنشاء نسخة من
الكائن وتغييره.
يوضح المثال أننا نقوم أولاً بإنشاء كائن فارغ ، ثم نسخ قيم الكائن وإجراء التغييرات ، والحصول في النهاية على كائن جديد وجاهز للاستخدام.
يرجى ملاحظة أن هذه الطريقة لن تعمل على النسخ العميق. بالحديث عن النسخ العميق ، نعني أنك بحاجة إلى نسخ كائن بخاصية واحدة أو أكثر.
const obj = {a : 1, b : { a : 1 } };
يقوم Object.assign () بنسخ خصائص الكائن ، لذلك إذا كانت قيمة الخاصية عبارة عن مؤشر إلى كائن ما ، يتم نسخ المؤشر فقط.
يتطلب النسخ العميق عملية عودية. يمكنك كتابة دالة هنا أو ببساطة استخدام طريقة
_.cloneDeep من مكتبة
Lodash .
مقارنة الكائنهناك طريقة رائعة للعمل مع تحويل الكائنات - خط. في المثال التالي ، نقوم بتحويل كلا الكائنين إلى سلاسل ومقارنتها:
JSON.stringify(obj1) === JSON.stringify(obj2)
هذا النهج مبرر ، لأنه في النهاية نقارن السلاسل التي تمثل المؤشر إلى نوع القيمة. الأخبار السيئة هي أنها لا تعمل دائمًا ، ويرجع ذلك أساسًا إلى عدم ضمان ترتيب واحد أو آخر لخصائص الكائن.
حل آخر جيد هو استخدام طريقة
_.isEqual من
Lodash ، التي تجري مقارنة عميقة للأشياء.
وقبل أن ننتهي ، دعنا نراجع بعض الأسئلة الشائعة حول الأشياء. سيساعد ذلك على التعمق في الموضوع ووضع المعرفة المكتسبة موضع التنفيذ.
حاول أن تفكر في الحل بنفسك قبل قراءة الإجابة.
كيف تعرف طول الجسم؟
للحصول على الإجابة ، من الضروري فرز جميع خصائص الكائن واحدًا تلو الآخر وحسابها. هناك عدة طرق للقيام بهذا التكرار:
- للداخل . تغطي هذه الطريقة جميع الخصائص القابلة للعد لجسم وسلسلة نموذجية له. لقد تعرّفنا على النموذج الأولي (وآمل أن نتعلم المادة) ، لذا يجب أن يكون واضحًا أن استخدام كلمة in لن يكون دائمًا صحيحًا للحصول على خصائص الكائن.
- Object.keys . تقوم هذه الطريقة بإرجاع صفيف بمفاتيح كل الخصائص القابلة للعد الخاصة به (التي تنتمي إلى الكائن المحدد). هذا النهج أفضل ، لأننا نعمل فقط على خصائص الكائن ، دون اللجوء إلى خصائص النموذج الأولي . ومع ذلك ، هناك حالات عندما تقوم بتعيين السمة التي يمكن عدها لبعض الخصائص على خطأ ، ويتجاهلها الكائن object.keys في النهاية ، وتحصل على نتيجة غير صحيحة. نادرًا ما يحدث هذا ، ولكن في مثل هذه الحالات ، سيكون getOwnPropertyNames مفيدًا .
- getOwnPropertyNames ترجع مصفوفة تحتوي على جميع مفاتيح الكائن (قابلة للعد وغير قابلة للعد).
تجدر الإشارة أيضًا إلى:
- يتكرر Object.values على خصائص العد الخاصة به ويعيد صفيفًا مع القيم المقابلة.
- يتكرر Object.entries على خصائص العد الخاصة به ويعيد صفيفًا بمفاتيح وقيمها .
أعتقد أنك لاحظت أن معظم الطرق المذكورة أعلاه تعرض مصفوفة. هذه فرصة للاستفادة الكاملة من طرق JavaScript للعمل مع المصفوفات.
إحدى هذه الطرق هي
array.length . في النهاية ، يمكننا فقط الكتابة
let objLength = Object.getOwnPropertyNames(obj).length;
كيف تتحقق مما إذا كان الكائن فارغًا؟
- JSON.stringify (myObj) === “{}” . نستخدم هنا مرة أخرى أداة تحويل السلاسل ، التي تجعل من السهل التحقق مما إذا كان الكائن فارغًا (مقارنة السلاسل ، وليس الكائنات).
- ! Object.keys (myobj) .length // true . كما ذكرت ، يمكن أن يكون تحويل مفاتيح الكائن إلى صفيف مفيدًا جدًا. هنا نستخدم طول الخاصية المناسب الموروث من Array.prototype ، مع التحقق من طول المفاتيح في الصفيف. في JS ، يتحول 0 إلى false ، لذا فإن إضافة ! نحولها إلى حقيقة. أي أرقام أخرى ستتحول إلى خطأ.
في الختام
آمل أن تشعر الآن بثقة أكبر في إنشاء الأشياء والعمل معها. دعونا نلخص:
- تذكر أن الكائنات تنتمي إلى نوع المرجع ، مما يعني أنه يوصى بالعمل معها دون تغيير الكائنات الأصلية.
- تكوين صداقات مع خاصية النموذج الأولي وسلسلة النموذج الأولي .
- تعرف على الأدوات المساعدة في التعامل مع الأشياء. تذكر أنه يمكنك تحويل الكائنات إلى سلاسل ، أو الحصول على مصفوفة بمفاتيحها ، أو ببساطة تكرار خصائصها باستخدام مجموعة من الأساليب التي التقينا بها.
حظا سعيدا في تعلم كائنات JavaScript.
