تم الاتفاق على تفسير ميراث JavaScript ، لكنه تأخر. دون مزيد من اللغط ، ما عليك سوى الوصول إلى هذه النقطة.
نظرًا لأنك تريد أن تفهم الميراث ، فإنه يثبت أن لديك بالفعل فهمًا معينًا لجافا سكريبت الموجهة نحو كائن. إذا كنت لا تفهم أي شيء ، فيمكنك الرجوع إلى التفسير الأساسي لـ JS الموجهة للكائنات ، ووضع المصنع ، ووضع المنشئ ، ووضع النموذج الأولي ، والوضع المختلط ، ووضع النموذج الديناميكي ".
سلسلة النموذج الأولي
أسهل طريقة لتنفيذ الميراث في JavaScript هي استخدام سلسلة النموذج الأولي وتوجيه النموذج الأولي لنوع الطفل إلى مثيل من نوع الوالد ، أي "النوع الفرعي. النمط النموذجي = نوع الوالد الجديد () ؛". طريقة التنفيذ هي كما يلي:
// إنشاء وظيفة مُنشئة SuperType () {this.name = ['Wuyuchang' ، 'Jack' ، 'tim'] ؛ this.property = true ؛} // إضافة طريقة supertype.prototype.getSuerPervalue = function () {return this.property ؛} // إنشاء دالة مُنشئة فرعية () {this.test = ['h1' ، 'h2' ، 'h3' ، 'h4'] ؛ This.subProperty = false ؛} // خطوات مفتاح لتنفيذ الميراث ، يشير النموذج الأولي للنوع الفرعي إلى مثيل لنوع الوالد الفرعي. النموذج الفرعي = جديد SuperType () ؛ // إضافة طريقة إلى نوع الطفل هنا. يجب أن يكون ذلك بعد تنفيذ الميراث ، وإلا فإن المؤشر سيشير إلى مثيل لنوع الأصل ، والطريقة فارغة. subtype.prototype.getSubValue = function () {return this.subproperty ؛}/* فيما يلي مثال رمز الاختبار*/var extal1 = new type () ؛ easule1.name.push ('wyc') ؛ eChate1.test.push ('h5') // truealert (extal1.getSubvalue ()) ؛ // falsealert (مثيل 1.name) ؛ // Wuyuchang ، Jack ، Tim ، Wycalert (extal1.test) ؛ // H1 ، H2 ، H3 ، H4 ، H5Var مثيل 2 = نوع فرعي جديد () ؛ تنبيه (مثيل 2.NAME) ؛ // Wuyuchang ، Jack ، Tim ، Wycalert (extal2.test) ؛ // H1 ، H2 ، H3 ، H4يمكنك أن ترى أن الكود أعلاه هو ميراث بسيط يتم تنفيذه من خلال سلسلة النموذج الأولي ، ولكن لا تزال هناك بعض المشكلات في مثال رمز الاختبار. أعتقد أنه بعد قراءة منشور مدونتي "التفسير الأساسي لـ JS الموجهة للكائنات ، وضع المصنع ، وضع المنشئ ، وضع النموذج الأولي ، الوضع المختلط ، وضع النموذج الأولي الديناميكي" ، يجب أن أعرف أن المشكلة الأولى في رمز سلسلة النموذج الأولي هي أن النموذج الأولي للنوع الفرعي هو مثيل لنوع الوالد ، وهو ما هو عليه ، وهي السمات الوالدة التي تتضمنها النموذج الوالد. سيتم مشاركة قيمة النوع بواسطة جميع الحالات . the exate1.name.push ('wyc') ؛ من الكود أعلاه يمكن أن يثبت وجود هذه المشكلة. المشكلة الثانية في سلسلة النموذج الأولي هي أنه عند إنشاء مثيل لنوع فرعي ، لا يمكن تمرير المعلمات إلى مُنشئ SuperType . لذلك ، في التطور الفعلي ، نادراً ما نستخدم سلاسل النموذج الأولي وحده.
مُنشئ الاقتراض
لحل مشكلتين في سلسلة النماذج الأولية ، بدأ المطورون في استخدام تقنية تسمى مقالات الاقتراض لحل المشكلات في سلسلة النموذج الأولي. فكرة التنفيذ لهذه التكنولوجيا بسيطة للغاية. تحتاج فقط إلى استدعاء مُنشئ النوع الأصل داخل مُنشئ النوع الفرعي. لا تنس أن الوظائف هي مجرد كائنات تنفذ الرمز في بيئة محددة ، لذلك يمكن تنفيذ المُنشئين من خلال طريقة تطبيق () أو Call () . الرمز كما يلي:
// إنشاء وظيفة مُنشئ SuperType (name) {this.name = name ؛ this.color = ['Pink' ، 'Yellow'] ؛ this.property = true ؛ this.testfun = function () {Alert ('http://tools.vevb.com/') ؛ }} // إضافة طريقة supertype.prototype.getSuerPervalue = function () {return this.property ؛} // إنشاء نوع فرعي للدالة (الاسم) {supertype.call (هذا ، الاسم) ؛ this.test = ['H1' ، 'H2' ، 'H3' ، 'H4'] ؛ this.subproperty = false ؛} // إضافة طريقة إلى النوع الفرعي هنا. تأكد من تنفيذ الميراث ، وإلا فإن المؤشر سيشار إلى مثيل لنوع الأصل ، والطريقة هي نوع فرعي فارغ. 'nick']) ؛ مثيل 1.name.push ('hello') ؛ easule1.test.push ('h5') ؛ easule1.color.push ('blue') ؛ easty1.testfun () ؛ // http://tools.vevb.com/alert(instance1.name) ؛ // Wuyuchang ، Jack ، Nick ، Hello // ALERT (eCHANE1.GetSuerPervalue ()) ؛ // تنبيه الخطأ (مثيل 1.Test) ؛ // H1 ، H2 ، H3 ، H4 ، H5 Alert (extal1.getSubvalue ()) ؛ // تنبيه كاذب (مثيل 1.Color) ؛ // pink ، yellow ، bluevar مثيل 2 = نوع فرعي جديد ('Wyc') ؛ easule2.testfun () ؛ // http://tools.vevb.com/alert(instance2.name) ؛ // Wyc // ALERT (extal2.getSuerPervalue ()) ؛ // تنبيه الخطأ (easule2.test) ؛ // H1 ، H2 ، H3 ، H4Alert (extue2.getSubValue ()) ؛ // falsealert (easule2.color) ؛ // الوردي ، الأصفريمكنك أن ترى أنه في الكود أعلاه ، يتم تحقيق مُنشئ النوع الفرعي من النوع الفرعي في الكود أعلاه ، وميراث السمة من خلال استدعاء نوع الوالد "supertype.call (هذا ، الاسم) ؛". يمكنك أيضًا نقل المعلمات إلى نوع الوالدين عند إنشاء النوع الفرعي ، لكن مشكلة جديدة تأتي. يمكنك أن ترى أنني حددت طريقة في مُنشئ النوع الأصل: TestFun ، وطريقة في النموذج الأولي لنوع الأصل: GetSuperValue. ومع ذلك ، بعد إنشاء إنشاء النوع الفرعي ، لا يزال من المستحيل استدعاء الطريقة التي يتم تعريف القيمة في النموذج الأولي لنوع الأصل ، ويمكنها فقط استدعاء طريقة المنشئ في النوع الأصل: TestFun. هذا هو نفسه استخدام وضع المنشئ فقط في إنشاء كائنات ، بحيث لا يكون للوظيفة أي قابلية لإعادة الاستخدام. مع الأخذ في الاعتبار هذه المشكلات ، نادراً ما تستخدم تقنيات مقاومة الاقتراض بمفردها.
الميراث المركب (سلسلة النموذج الأولي + مُنشئ الاقتراض)
كما يوحي الاسم ، فإن الوراثة الجمعية هي نمط يتكون من مزايا الجمع بين استخدام سلاسل النموذج الأولي ومصمم الاقتراض. التنفيذ هو أيضا بسيط جدا. نظرًا لأنها مزيج ، بالطبع ، يجمع بين مزايا كلا الطرفين ، وهي طريقة ميراث سلسلة النموذج الأولي ، والسمات المورزة . يتم تنفيذ الرمز المحدد على النحو التالي:
// إنشاء وظيفة مُنشئ SuperType (name) {this.name = name ؛ this.color = ['Pink' ، 'Yellow'] ؛ this.property = true ؛ this.testfun = function () {Alert ('http://tools.vevb.com/') ؛ }} // إضافة طريقة supertype.prototype.getSuerPervalue = function () {return this.property ؛} // إنشاء نوع فرعي للدالة (الاسم) {supertype.call (هذا ، الاسم) ؛ this.test = ['H1' ، 'H2' ، 'H3' ، 'H4'] ؛ this.subproperty = false ؛} نوع فرعي. يجب أن يكون ذلك بعد تنفيذ الميراث ، وإلا فإن المؤشر سيشير إلى مثيل لنوع الأصل ، والطريقة هي نوع فرعي فارغ. 'nick']) ؛ مثيل 1.name.push ('hello') ؛ easule1.test.push ('h5') ؛ easule1.color.push ('blue') ؛ easty1.testfun () ؛ // http://tools.vevb.com/alert(instance1.name) ؛ // Wuyuchang ، Jack ، Nick ، Helloalert (extal1.getSuerPervalue ()) ؛ // truealert (extal1.test) ؛ // H1 ، H2 ، H3 ، H4 ، H5 Alert (extal1.getSubvalue ()) ؛ // تنبيه كاذب (مثيل 1.Color) ؛ // pink ، yellow ، bluevar مثيل 2 = نوع فرعي جديد ('Wyc') ؛ easule2.testfun () ؛ // http://tools.vevb.com/alert(instance2.name) ؛ // WYC ALERT (eCHANTY2.GETSUERPERVALUE ()) ؛ // truealert (extal2.test) ؛ // H1 ، H2 ، H3 ، H4Alert (extue2.getSubValue ()) ؛ // falsealert (easule2.color) ؛ // الوردي ، الأصفريرث الرمز أعلاه خصائص نوع الأصل من خلال supertype.call (هذا ، الاسم) ؛ ويرث أساليب النوع الأصل من خلال النوع الفرعي. النموذج = جديد supertype () ؛. يحل الرمز أعلاه بشكل مريح المشكلات التي تواجهها سلاسل النموذج الأولي ومصمم الاقتراض ، وأصبحت الطريقة الأكثر استخدامًا للميراث على سبيل المثال في JavaScript. ومع ذلك ، فإن الوضع المختلط لا يخلو من أوجه القصور. يمكن ملاحظة أنه في الكود أعلاه ، تم بالفعل مورث سمات نوع الأصل عند وراثة الطريقة. ومع ذلك ، يتم مشاركة النوع المرجعي في هذا الوقت. لذلك ، يتم استدعاء مُنشئ نوع الأصل في مُنشئ نوع الطفل بعد النوع الفرعي ، وبالتالي يرث سمات نوع الأصل للكتابة فوق السمات الموروثة في النموذج الأولي. من الواضح أنه ليس من الضروري استدعاء المُنشئ مرتين ، ولكن هل هناك أي طريقة لحلها؟ عند حل هذه المشكلة ، انظر أولاً إلى الوضعين التاليين.
النموذج الأولي الميراث
تختلف طريقة تنفيذ ميراث النموذج الأولي عن طريقة الميراث العادي. لا يستخدم ميراث النموذج الأولي مُنشئًا بالمعنى الدقيق للكلمة ، ولكنه يستخدم النموذج الأولي بدلاً من ذلك لإنشاء كائنات جديدة تعتمد على الكائنات الموجودة ، وليس هناك حاجة لإنشاء أنواع مخصصة نتيجة لذلك. الرمز المحدد كما يلي:
كائن الدالة (o) {function f () {} f.prototype = o ؛ إرجاع جديد f () ؛}مثال رمز:
/* الوراثة النموذجية*/كائن الوظيفة (O) {function f () {} f.prototype = o ؛ إرجاع new f () ؛} var person = {name: 'wuyuchang' ، الأصدقاء: ['wyc' ، 'nicholas' ، 'tim']} var otherperson = object (person) ؛ otherperson.name = 'greg' ؛ otherperson.pshels.push ('bob') ؛ var otherperson2 = object (person) ؛ otherperson2.name = 'jack' ؛ otherperson2.friends.push ('Rose') ؛ Alert (person.friends) ؛ // WYC ، نيكولاس ، تيم ، بوب ، روزالميراث الطفيلي
/* الوراثة الطفيلية*/الوظيفة createAnothOther (Original) {var clone = Object (Original) ؛ clone.sayhi = function () {Alert ('hi') ؛ } return clone ؛}مثال على الاستخدام:
/* الوراثة النموذجية*/كائن الوظيفة (O) {function f () {} f.prototype = o ؛ إرجاع new f () ؛} /* الميراث الطفيلي* /الوظيفة createanothOther (Original) {var clone = Object (Original) ؛ clone.sayhi = function () {Alert ('hi') ؛ } return clone ؛} var person = {name: 'wuyuchang' ، الأصدقاء: ['wyc' ، 'nicholas' ، 'rose']} var otherperson = createanother (person) ؛ شخص آخر. sayhi () ؛الجمع الطفيلي الميراث
ذكرت في وقت سابق عيوب تنفيذ نمط الجمع بين الميراث في جافا سكريبت. الآن دعونا نحل أوجه القصور. تتمثل فكرة التنفيذ في أن ترث سمات المُنشئين ، ولا تحتاج طريقة ميراث النموذج المختلط لسلسلة النموذج الأولي إلى إنشاء إنشاء مُنشئ نوع الأصل عند ورث الطريقة. الرمز كما يلي:
كائن الدالة (o) {function f () {} f.prototype = o ؛ إرجاع جديد f () ؛}/* الميراث المركب الطفيلي*/وظيفة الوراثة النمط (النوع الفرعي ، supertype) {var ortotype = object (supertype.prototype) ؛ النموذج الأولي. constructor = النوع الفرعي ؛ النموذج الفرعي. النموذج = النموذج الأولي ؛}عند استخدامه ، تحتاج فقط إلى استبدال سطر التعليمات البرمجية "النوع الفرعي. النموذج = جديد SuperType () ؛" في وضع المركب مع النمط الوراثي (النوع الفرعي ، superType) ؛. تنعكس كفاءة الميراث التوافقي الطفيلي من حيث أنه يطلق على مُنشئ نوع الوالدين مرة واحدة فقط ، مع تجنب إنشاء خصائص غير ضرورية أو زائدة عن الحاجة. في الوقت نفسه ، يمكن أن تظل سلسلة النموذج الأولي دون تغيير ، لذلك يمكن أيضًا استخدام مثيل و isProtypeOF () بشكل طبيعي. هذه أيضًا طريقة الميراث المثالية في الوقت الحاضر ، وهي تتحول حاليًا إلى هذا النموذج. (يوي يستخدم هذا الوضع أيضًا.)
يشير منشور المدونة هذا إلى "JavaScript Advanced Programming Edition". تتم إعادة كتابة الرمز وأكثر تحديدًا ، وعلق على تسهيل فهم الجميع. إذا كان لديك رؤى فريدة من نوعها في ميراث JS ، فلا تخيل. الرد على آرائك للرجوع إليه!