في الآونة الأخيرة ، أشاهد "برمجة JavaScript Advanced" (الطبعة الثانية)
إنشاء كائنات في جافا سكريبت
• وضع المصنع
• وضع المنشئ
• وضع النموذج الأولي
• الجمع بين نمط المُنشئ والنموذج الأولي
• النموذج الأولي الوضع الديناميكي
تحتوي معظم اللغات الموجهة نحو الكائنات على مفهوم الفصل ، حيث يمكن من خلالها إنشاء كائنات متعددة بنفس الأساليب والسمات. على الرغم من من الناحية الفنية ، فإن JavaScript هي لغة موجهة نحو الكائن ، إلا أن JavaScript لا تتمتع بمفهوم الفئات ، إلا أن كل شيء هو كائن. أي كائن هو مثيل لنوع مرجعي معين ويتم إنشاؤه من خلال أنواع المراجع الموجودة ؛ يمكن أن يكون النوع المرجعي أصليًا أو مخصصًا. أنواع المراجع الأصلية هي: كائن ، صفيف ، بيانات ، regexp ، الدالة. ! النوع المرجعي هو بنية بيانات تنظم البيانات والوظائف معًا ، وعادة ما تسمى فئة. في JavaScript التي تفتقر إلى مفهوم الفصل ، فإن المشكلة التي يجب حلها هي كيفية إنشاء كائنات بكفاءة.
1.1.0. الطرق العامة لإنشاء الكائنات
var person = {} ؛ // الكائن الحرفي التمثيل المعادل لـ var person = new objCect () ؛ person.name = 'evansdiy' ؛ person.age = '22' ؛ person.friends = ['ajiao' ، 'tiantian' ، 'pangzi'] ؛ person.logname = function () {console.log (this.name) ؛}بناءً على نوع مرجع الكائن ، يتم إنشاء كائن ، والذي يحتوي على أربع خصائص ، واحدة منها طريقة. إذا كنت بحاجة إلى العديد من مثيلات مثل الشخص ، فسيكون هناك الكثير من التعليمات البرمجية المكررة.
1.1.1. نموذج المصنع
قم بإنشاء كائن مع وظيفة يمكن أن تحتوي على تفاصيل الكائن ثم إرجاع الكائن.
وظيفة الشخص (الاسم ، العمر ، الأصدقاء) {var o = {name: name ، age: age ، friends: friends ، logName: function () {console.log (this.name) ؛ }} ؛ return o ؛} var person1 = person ('Evansdiy' ، '22' ، ['Ajiao' ، 'Tiantian' ، 'Pangzi']) ؛في كل مرة يتم فيها استدعاء وظيفة الشخص ، يتم إنشاء كائن جديد من خلال الكائن O داخل الوظيفة ، ثم يتم إرجاعه. بصرف النظر عن هذا ، يوجد هذا الكائن الداخلي O لإنشاء كائن جديد ليس له غرض آخر. بالإضافة إلى ذلك ، من المستحيل تحديد نوع الكائن الذي تم إنشاؤه بواسطة وضع المصنع.
1.1.2. وضع المنشئ
وظيفة الشخص (الاسم ، العمر ، الوظيفة) {this.name = name ؛ this.age = العمر ؛ this.job = Job ؛ this.logname = function () {console.log (this.name) ؛ }} // قم بإنشاء مثيل للشخص من خلال المشغل الجديد var person1 = شخص جديد ('boy-a' ، '22' ، 'worker') ؛ var person2 = شخص جديد ('Girl-b' ، '23' ، 'Teacher') ؛ person1.logname () ؛ //boy-aperson2.logname () ؛ // girl-aمقارنة بوضع المصنع ، يمكننا أن نجد أنه لا توجد حاجة لإنشاء كائنات وسيطة هنا ، لا توجد عودة. بالإضافة إلى ذلك ، يمكن التعرف على مثيل المنشئ كنوع محدد ، يحل مشكلة التعرف على الكائن (عن طريق التحقق من سمة مُنشئ المثيل ، أو استخدام عامل التشغيل من أجل التحقق مما إذا تم إنشاء المثيل بواسطة مُنشئ).
console.log (person1.constructor == شخص)
console.log (person1 مثيل الشخص) ؛ // استخدم مشغل مثيل لتحديد ما إذا كان الشخص 1 هو مثيل لشخص مُنشئ ، لكن نمط المنشئ لديه أيضًا مشاكله الخاصة. في الواقع ، سيتم إعادة إنشاء طريقة logName مرة واحدة في كل حالة. تجدر الإشارة إلى أن الأساليب التي أنشأتها إنشاء مثيل ليست متساوية ، وسيصبح الرمز التالي خطأ:
console.log (person1.logname == person2.logname) ؛ // false يمكننا نقل الطريقة خارج المنشئ (تم تغييرها إلى وظيفة عالمية) لحل هذه المشكلة:
دالة logName () {console.log (this.name) ؛} وظيفة logage () {console.log (this.age) ؛}ومع ذلك ، لا يمكن استدعاء الوظائف العالمية التي تم إنشاؤها عالميًا إلا من خلال الحالات التي أنشأها الشخص ، وهو أمر غير واقعي بعض الشيء ؛ إذا كان هناك العديد من الطرق ، فلا يزال هناك حاجة إلى تعريف واحد تلو الآخر ، ويفتقرون إلى التغليف.
1.1.3. وضع النموذج الأولي
تحتوي كل وظيفة في JavaScript على مؤشر إلى سمة النموذج الأولي (يمكن لمعظم المتصفحات الوصول إليها من خلال السمة الداخلية __proto__) ، سمة النموذج الأولي هي كائن يحتوي على خصائص وطرق مشتركة بواسطة جميع الحالات التي تم إنشاؤها بواسطة نوع مرجعي معين.
وظيفة person () {} person.name = 'evansdiy' ؛ person.prototype.friends = ['ajiao' ، 'jianjian' ، 'pangzi'] ؛ person.prototype.logname = function () {console.log (this.name) ؛الرمز أعلاه يفعل هذه الأشياء:
1. تحديد شخص مُنشئ. تحصل وظيفة الشخص تلقائيًا على خاصية النموذج الأولي. تحتوي هذه الخاصية فقط على خاصية مُنشأة تشير إلى الشخص بشكل افتراضي ؛
2. أضف ثلاث سمات من خلال الشخص. النمط النمط ، يتم استخدام إحداها كطريقة ؛
3. قم بإنشاء مثيل للشخص ، ثم اتصل بطريقة logName () على المثيل. !
ما تحتاج إلى ملاحظته هنا هو عملية استدعاء طريقة logName ():
1. ابحث عن طريقة logName () على مثيل Person1 ووجدت أنه لا توجد طريقة من هذا القبيل ، لذلك عدت إلى النموذج الأولي للشخص 1
2. ابحث عن طريقة Logame () على النموذج الأولي لـ Person1. هناك هذه الطريقة. لذلك نسمي هذه الطريقة بناءً على عملية البحث هذه. يمكننا منع المثيل من الوصول إلى سمة اسم نفس النموذج الأولي عن طريق تحديد السمة ذات الاسم نفسه في النموذج الأولي على المثيل. تجدر الإشارة إلى أن القيام بذلك لن يحذف سمة اسم نفس النموذج الأولي ، ولكنه سيمنع الوصول فقط من الوصول.
var person2 = شخص جديد () ؛
person2.name = 'laocai' ؛ إذا لم نعد بحاجة إلى خصائص على المثيل ، فيمكننا حذفها من خلال مشغل الحذف.
حذف person2.name ؛ استخدم حلقة FO-in لتعداد جميع السمات التي يمكن أن يصل إليها المثيل (بغض النظر عما إذا كانت السمة موجودة في المثيل أو في النموذج الأولي):
لـ (i in person1) {console.log (i) ؛}في الوقت نفسه ، يمكنك أيضًا استخدام طريقة HasownProperty () لتحديد ما إذا كانت خاصية معينة موجودة على المثيل أو في النموذج الأولي. فقط عند وجود العقار في المثال ، سيتم إرجاع صحيح:
console.log (person1.hasownproperty ('name')) ؛ // true! يأتي HasownProperty من النموذج الأولي للكائن وهو الطريقة الوحيدة في JavaScript لعدم البحث عن سلسلة النموذج الأولي عند معالجة الخصائص. [عبر حديقة JavaScript Secret] بالإضافة إلى ذلك ، يمكنك أيضًا استخدام طريقة المشغل و HasownProperty () لتحديد ما إذا كانت خاصية معينة موجودة في المثيل أو في النموذج الأولي:
console.log (('Friends' in Person1) &&! person1.hasownproperty ('friends')) ؛ أولاً حدد ما إذا كان الشخص 1 يمكنه الوصول إلى خاصية الأصدقاء. إذا كان ذلك ممكنًا ، فحدد ما إذا كانت هذه الخاصية موجودة في المثيل (لاحظ السابق!). إذا لم يكن موجودًا في الحالة ، فهذا يعني أن هذه الخاصية موجودة في النموذج الأولي. كما ذكرنا سابقًا ، فإن النموذج الأولي هو أيضًا كائن ، حتى نتمكن من كتابة النموذج الأولي باستخدام التمثيل الحرفي للكائن. يمكن تعديل طريقة الكتابة السابقة لإضافة التعليمات البرمجية إلى النموذج الأولي إلى:
person.prototype = {name: 'Evansdiy' ، الأصدقاء: ['ajiao' ، 'Jianjian' ، 'Pangzi'] ، logName: function () {console.log (this.name) ؛ }}نظرًا لأن بناء الجملة الحرفي الكائن يعيد كتابة النموذج الأولي لأكمله ، فإن سمة المنشئ التي تم الحصول عليها افتراضيًا عند إنشاء المُنشئ ستشير إلى مُنشئ الكائن:
// بعد إعادة كتابة الكائن الحرفي النموذج الأولي
console.log (person1.constructor) ؛ // object ومع ذلك ، سيظل عامل مثيل OF يعيد النتيجة المطلوبة:
// بعد إعادة كتابة الكائن الحرفي النموذج الأولي
console.log (person1 مثيل الشخص) ؛ // صحيح بالطبع ، يمكنك تعيين قيمة المنشئ يدويًا في النموذج الأولي لحل هذه المشكلة.
person.prototype = {مُنشئ: شخص ، ......}إذا تم تعديل كائن النموذج الأولي بعد إنشاء مثيل الكائن ، فسوف ينعكس تعديل النموذج الأولي على الفور في جميع مثيلات الكائنات:
وظيفة person () {} ؛ var person1 = new person () ؛ person.prototype.name = 'evansdiy' ؛ console.log (person1.name) ؛ // 'evansdiy'العلاقة بين مثيل ونموذج أولي هو مجرد مؤشر ، وليس نسخة من النموذج الأولي. النموذج الأولي هو في الواقع عملية بحث. سيتم عكس أي تعديلات تم إجراؤها على كائن النموذج الأولي في جميع حالات الكائن ، حتى لو تم تعديل النموذج الأولي بعد إنشاء المثيل. ماذا لو تم إعادة كتابة كائن النموذج الأولي بعد إنشاء مثيل كائن؟
وظيفة person () {} ؛ var person1 = new person1 () ؛ // يشير المثيل الذي تم إنشاؤه إلى النموذج الأولي الأصلي // person.prototype = {friends: ['ajiao' ، 'jianjian' ، 'pangzi']} var person2 = new person () ؛ console.log (person1.friends) ؛سيكون للرمز أعلاه خطأ غير محدد عند تنفيذه إلى السطر الأخير. إذا استخدمنا من أجل تعداد الخصائص التي يمكن الوصول إليها في Person1 ، فسنجد أنه لا يوجد شيء في الداخل ، ولكن يمكن لـ Person2 الوصول إلى سمة الأصدقاء على النموذج الأولي. ! إعادة كتابة النموذج الأولي يقطع الاتصال بين النموذج الأولي الحالي وجميع مثيلات الكائنات التي تم إنشاؤها من قبل. لا يزال هناك النموذج الأولي لمثيل الكائن الذي تم إنشاؤه من قبل ، لكنه قديم.
// عند إنشاء شخص 1 ، لم يتم إعادة كتابة كائن النموذج الأولي بعد. لذلك ، لا يزال المُنشئ في كائن النموذج الأولي هو الشخص الافتراضي () console.log (person1.constructor) ؛ // person () // لكن مُنشئ Person2 نقاط إلى object () console.log (person2.constructor) ؛ // object ()
تجدر الإشارة إلى أن نمط النموذج الأولي يتجاهل عملية تمرير المعلمات للمشارك ، وأن جميع الحالات تحصل على نفس قيمة السمة. في الوقت نفسه ، هناك مشكلة كبيرة في نمط النموذج الأولي ، أي أن قيمة نوع المرجع في كائن النموذج الأولي ستتم مشاركتها بواسطة جميع الحالات ، وسيتم أيضًا تعديل قيمة نوع المرجع في جميع مثيلات الكائنات.
وظيفة person () {} ؛ person.prototype = {friends: ['ajiao' ، 'tiantian' ، 'pangzi']} var person1 = new personيعني تعديل قيمة النوع المرجعي للأصدقاء Person1 أن الأصدقاء في Person2 سيتغيرون أيضًا. في الواقع ، فإن الأصدقاء الذين تم حفظهم في النموذج الأولي هم في الواقع مجرد مؤشر لقيمة الأصدقاء في الكومة (يتم إصلاح طول هذا المؤشر وحفظه على المكدس). عندما يصل المثيل إلى قيمة نوع المرجع من خلال النموذج الأولي ، يتم الوصول إليه أيضًا بواسطة المؤشر بدلاً من الوصول إلى النسخة على المثيل المعني (مثل هذه النسخة غير موجودة).
1.1.4. قم بإنشاء كائنات بالاشتراك مع نمط المنشئ والنموذج الأولي
الجمع بين مزايا المُنشئ ووضع النموذج الأولي ، والتعويض عن أوجه القصور الخاصة بهم ، وذلك باستخدام المُنشئين لتمرير معلمات التهيئة ، وتحديد سمات المثيل فيها ، واستخدام النماذج الأولية لتحديد الطرق الشائعة والسمات العامة. هذا الوضع يستخدم على نطاق واسع.
وظيفة الشخص (الاسم ، العمر) {this.name = name ؛ this.age = العمر ؛ this.friends = ['ajiao' ، 'Jianjian' ، 'pangzi'] ؛ }} var person1 = شخص جديد ('evansdiy' ، '22') ؛ var person2 = شخص جديد ('amy' ، '21') ؛ person1.logname () ؛ // 'Evansdiy'person1.friends.push (' haixao ')1.1.5. النموذج الأولي الوضع الديناميكي
يلف الوضع الديناميكي النموذجية جميع المعلومات المطلوبة في المُنشئ ، ويستخدم عبارة IF لتحديد خاصية معينة في النموذج الأولي. إذا لم يكن موجودًا (عندما يتم استدعاء المُنشئ لأول مرة) ، قم بتنفيذ رمز تهيئة النموذج الأولي داخل العبارة IF.
وظيفة الشخص (الاسم ، العمر) {this.name = name ؛ this.age = العمر ؛ if (typeof this.logname! = 'function') {person.prototype.logname = function () {console.log (this.name) ؛ } ؛ person.prototype.logage = function () {console.log (this.age) ؛ } ؛ } ؛ } ؛} var person1 = شخص جديد ('Evansdiy' ، '22') ؛ // تم استدعاء المنشئ لأول مرة ، وتم تعديل النموذج الأولي في هذا الوقت. var person2 = شخص جديد ('amy' ، '21') ؛ // طريقة logName () موجودة بالفعل ولن يتم تعديل النموذج الأولي مرة أخرىتجدر الإشارة إلى أن هذا النمط لا يمكنه استخدام بناء الجملة الحرفي للكائن لكتابة كائنات النموذج الأولي (سيؤدي ذلك إلى تجاوز كائنات النموذج الأولي). إذا تم إعادة كتابة النموذج الأولي ، فلن يحتوي كائن النموذج الأولي على الحالة الأولى التي تم إنشاؤها بواسطة المنشئ على خصائص كائن النموذج الأولي في العبارة IF.
وظيفة الشخص (الاسم ، العمر) {this.name = name ؛ this.age = العمر ؛ if (typeof this.logname! = 'function') {person.prototype = {logName: function () {console.log (this.name) ؛ } ، logage: function () {console.log (this.age) ؛ }} سترتجدر الإشارة إلى أن كل نموذج له سيناريوهات التطبيق الخاصة به ، ولا يهم مزاياه وعيوبه.
التحليل أعلاه للأنماط المختلفة لإنشاء كائنات في JavaScript هو كل المحتوى الذي أشاركه معك. آمل أن يعطيك مرجعًا وآمل أن تتمكن من دعم wulin.com أكثر.