جافا سكريبت الوراثة من وجهة نظر الطالب الذي يذاكر كثيرا بالملل: مصنع البنائين

مصباح النور والتفاح هذه قصة عن قطعة واحدة خاصة جدًا من JavaScript ، وهي اللغة الاصطناعية الأكثر استخدامًا في العالم اليوم (2019).

تقدم هذه المقالة نوعًا من النظرة الفلسفية للميراث في جافا سكريبت ، وأتمنى ألا يكون ذلك إلا بناءً على مصدر المعرفة الأكثر إثارة: الحياة نفسها بكل مظاهرها. لا أعرف إذا كان هذا مصدر إلهام عند إنشاء تصميم سلسلة النموذج الأولي في JavaScript.

ولكن إذا كان الأمر كذلك ، فهذا أمر مهم وقوي لدرجة أنه عندما أبدأ في التفكير في الأمر ، قد يصعب التنفس أحيانًا ...

(كل الروابط مظللة )


أنا متأكد أيضًا من أن أحداً منا لن يشك في أن بريندان آيك (Eich) - مؤلف لغة برمجة جافا سكريبت - هو عبقري رائع! وليس فقط لأنه يكرر في كثير من الأحيان:
راهن دائمًا على JavaScript!
لنبدأ! وستكون نقطة الانطلاق الأولى لدينا هي الخيال ، حيث نوقف أولاً كل التحيزات والإغفالات والآثار الجانبية الأخرى.

نحن في طريق العودة إلى المستقبل ، الحقبة التي سبقت إنشاء الإنترنت الحديثة في أوائل التسعينيات.

من وقت أول قراصنة اخترعوا كل ما نستخدمه الآن ( موظفو تكنولوجيا المعلومات ) ، كنا نتحرك إلى رسم مثير للإعجاب: حول الحرب بين المتصفحات Netstcape Navigator 2 و Internet Explorer 3. لقد خرجت للتو Java ، ولم يتم اختراع كل شيء تقريبًا من الإنترنت الحديث أو حتى الآن ليس قبل فتح. من الممكن ، مثلي ، في تلك "الأيام الخوالي" أن تكون شابًا ، ويمكن أن تتذكر هذا الشعور الرائع بالتورط في كل الروعة التي يتم إنشاؤها أمام عينيك مباشرةً.

لذلك ، لديك جهاز كمبيوتر قوي للغاية على أحدث طراز Intell Pentium 200 MMX مع ذاكرة وصول عشوائي تبلغ 32 ميجابايت أو Windows 3.11 أو حتى Windows 95 وأنت تتطلع إلى المستقبل بأمل! وبالطبع ، يتم تثبيت كلا المستعرضين أيضًا. لديك طلب هاتفي ، يمكنك من خلاله الاتصال بالشبكة بحثًا عن البريد العشوائي الجديد أيضًا للدراسة أو للدردشة فقط. على الرغم من أنه لا يزال يتعذر عليك الدردشة مباشرة في المتصفح ، فمن الأرجح أنك تستخدم أنظمة تسليم الرسائل المؤجلة أو شيء ما مثل البريد الإلكتروني أو ربما UseNet ، أو ربما تتقن بالفعل التسليم الفوري عبر IRC .

يمر عامان ويتغير كل شيء حرفيًا ... فجأة تشاهد الرسوم المتحركة لرقائق الثلج على صفحات الويب لتهنئتك بالعام الجديد وعيد الميلاد. بالطبع ، أنت مهتم بكيفية القيام بذلك ، واكتشاف لغة جديدة - JavaScript. نظرًا لأن HTML ليس جديدًا بالنسبة لك ، فقد بدأت تعلم هذه التقنية الفنية الجذابة. ستكتشف قريباً CSS ويتبين أن هذا مهم أيضًا ، لأن كل شيء مصنوع الآن من مجموعة من هذه العناصر الثلاثة: HTML و JavaSript و CSS. نجاح باهر.

في الوقت نفسه تقريبًا ، قد تلاحظ وجود شيئين رائعين في Windows نفسه ، وظهرت CScript و HTA فيه ، وحتى بعد ذلك أصبح من الممكن إنشاء تطبيقات سطح مكتب كاملة مباشرة على JS (وهذا لا يزال يعمل).

وهكذا بدأت في إنشاء أول خادم ويب ، ربما في Perl أو C ~ C ++ . ربما بدأت في استخدام أنظمة تشغيل Unix-like وقمت بذلك على bash . وكل ذلك "غزل الغزل" بفضل واجهة البوابة العامة (لا تخلط بينه وبين CGI الأخرى). لا يزال PHP غير موجود تقريبًا ، ولكن ربما ستعجبك قريبًا.

عصر 200x. أنت الآن تفعل ASP في JScript . هذا مشابه جدًا لجافا سكريبت التي تعمل داخل صفحات الويب الخاصة بك. هذا رائع جدا! أنت تفكر في إنشاء محرك القالب الخاص بك ، وهو نوع من محاكاة ساخرة XML . ثم فجأة يقوم شخص ما باستدعاء أجاكس بكل هذه الطرق الممتعة لتحميل المحتوى الذي تستخدمه ديناميكيًا لعدة سنوات حتى الآن. وكلهم يعتقدون الآن أن هناك فقط XMLHTTPRequest ، لكنك تتذكر أنه يمكن نقل البيانات إلى BMP أو IFrame أو حتى عن طريق إدراج العلامة <script> . وبعد ذلك يتحدث شخص فجأة بحماس عن JSON ومدى فائدة ذلك ، عندما كنت تقود البيانات إلى الأبد مع شيء مثل هذا:

document.write("<" + "script src=" + path + ">"); 

الأمر ليس كذلك الآن ، لكن لا يزال بإمكانك تذكر كيف ...

عندما تصل إلى حواسك ، تبدأ من وقت لآخر في أن تجد نفسك تتجول مع Rhino أو Nashorn في محاولات لإرضاء رغبات عملاء Java باستخدام Alfresco أو Asterisk . لقد سمعت بالفعل عن ظهور وشيك لجافا سكريبت في عالم الرقائق ، وأنت مستوحى من هذا الخبر. وبالطبع ، الآن لديك مسج والعمود الفقري .

عند مشاهدة تساقط الثلوج في عام 2010 القادم ، أنت تعلم بالفعل أن جميع قواعد اللعبة ستتغير قريبًا ، حيث إن "اللاعب رقم 1" قد دخل إلى الحقل: Node.js. وفي السنوات العشر القادمة ، ستقضيها مع هذه اللعبة الجديدة ، وحتى الآن ، في عام 2019 ، لا يزال لا يمكنك الحصول على ما يكفي من روعة.

بشكل عام ، أنت سعيد بكل شيء ، كل شيء يناسبك ، كل هذه الألعاب والألعاب فيها تشكل جزءًا كبيرًا من اهتمامات حياتك.

ولكن هناك سؤال صغير تطرحه على نفسك يومًا بعد يوم ، ليلة بعد ليلة على مدار عقدين من الزمن:

إذا كان عليك القيام بذلك ، فكيف تفسر استخدام Empathy باستخدام JavaScript؟


أنت تعلم أن واحدة من أكثر المواضيع تعقيدًا في JavaScript هي Prototype Inheritance وسلسلة Prototype . وأنت تحب هذا الموضوع ، يمكنك شرح كيف يعمل ويعمل كل شيء ، لمجرد أنك تعلمته من البداية تقريبًا ، حتى قبل أن يولد الإصدار الأول من Standard ، وأين ، كما تتذكر ، هناك 4.2 .1 الكائنات :
يدعم ECMAScript الوراثة المستندة إلى النموذج الأولي. يحتوي كل مُنشئ على نموذج أولي مرتبط ، ولكل كائن تم إنشاؤه بواسطة هذا المُنشئ مرجعًا ضمنيًا إلى النموذج الأولي (يُسمى النموذج الأولي للكائن) المرتبط بمنشئه. علاوة على ذلك ، قد يحتوي النموذج الأولي على إشارة ضمنية غير فارغة إلى النموذج الأولي الخاص به ، وما إلى ذلك ؛ وهذا ما يسمى سلسلة النموذج الأولي .
يتم إنشاء كل كائن مع إشارة ضمنية إلى النموذج الأولي. وهذا ما يسمى سلسلة الميراث النموذج ، والتي يمكنك الاستمرار طالما أردت.

واو ... وإذا فجأة ، مثلي ، قد تفكر في أن هذا هو واحد من أعظم الاختراعات في Compuer Science ، فكيف يمكنك التعبير عن التأثير الذي أثرت عليه قراءة هذا البيان عليك؟

دعنا نعود إلى البداية. في الفناء 1995. أنت بريندان آيك ، وتحتاج إلى اختراع لغة برمجة جديدة. ربما تحب Lisp أو Scheme ، على الأقل بعض الأجزاء المفضلة لديهم. وتواجه الحاجة إلى حل مشكلة الميراث ، حيث يجب عليك التظاهر بأن اللغة لديها تطبيق معين لـ OOP . دعنا نفكر : تحتاج إلى مزج كل الأشياء التي تحبها ، وربما أيضًا بعض الأشياء التي لا تحبها ، ويجب أن تكون الكوكتيل الناتج جيدًا بما يكفي حتى لا يلاحظ أحد خدعة حتى تكون هناك حاجة حقيقية لفهم كيف هي رتبت في الداخل.

والسؤال الآن هو: ماذا سيحدث للميراث؟

دعنا نعود إلى الواقع للحظة. ماذا نعرف جميعا عن الميراث؟ بعض الإجابات الواضحة على هذا السؤال:

  1. وتستند معظم الأشكال الحية على الجينوم . إنه مستودع معلومات حول الخصائص المحتملة والسلوك المزعوم للكائنات الحية. عندما تكون كائنًا حيًا ، فأنت تحمل جزءًا من الجينوم داخلك ، ويمكنك توزيعه ، لكنك استلمته من الأجيال السابقة.
  2. يمكنك إنشاء كائن حي باستخدام تقنيتين: المزيج (الجينومات) لأسلاف ، أو ربما استخدام استنساخ monoecious لأحدهما . بالطبع ، نحن اليوم تقنيات متاحة تسمح بخلط جينومات أكثر من مخلوق واحد ، لكن هذا أقل وضوحًا وغير طبيعي.
  3. عامل الوقت مهم. إذا لم يكن هناك خاصية موروثة ، أو لم تكن بالفعل ، فإن المخرج الوحيد لدينا هو إنشائها من الصفر. بالإضافة إلى ذلك ، هناك أيضًا الميراث ، الذي ينتقل إلى المخلوق من أسلافه ليس من خلال الجينوم ، ولكن من خلال قوانين الملكية ، وهذا يمكن أن يكون مهمًا أيضًا.

بالعودة إلى الماضي ، والسؤال الصحيح الذي نحتاج إلى طرحه هو الآن: وفي الواقع ، الميراث ماذا نريد أن نحصل عليه؟

حسنًا ، على أي حال ، في عملية حل مشكلة الميراث ، نحتاج على الأقل إلى سد الفجوة بين البرمجة والحياة الحقيقية ، وإلا ، بشكل عام ، لن يكون لنا أي حق في تسميتها الوراثة.

دعونا الآن ننتهي: نحن في الخمسينيات من القرن الماضي ، ولدينا جهاز كمبيوتر قوي به 32 ميغابايت فقط من ذاكرة الوصول العشوائي ، ونحن نحاول إنشاء لغة مترجمة ، لذلك علينا أن نهتم كثيرًا بهذه الذاكرة. تستهلك كل قطعة من البيانات ، خاصة كائنات السلسلة ، الكثير من الذاكرة ، ويجب أن نكون قادرين على إعلان هذه القطعة مرة واحدة فقط ، وكلما كان ذلك ممكنًا في المستقبل ، استخدم دائمًا المؤشرات فقط إلى منطقة الذاكرة التي تشغلها هذه القطعة. نلخص: سؤال صعب للغاية.

هناك رأي شائع: " يتم إنشاء JavaScript من الكائنات ." باستخدام هذا التفاهات ، يمكننا بسهولة الإجابة عن السؤال " من ماذا " للوراثة و " ماذا ": من الكائنات إلى الكائنات. من أجل قضية حفظ الذاكرة ، اتضح أنه يجب تخزين جميع البيانات في هذه الكائنات ، ويجب أيضًا تخزين جميع روابط البيانات هذه في الخصائص الموروثة لهذه الكائنات. ربما أصبح من الواضح الآن السبب الذي جعلنا نحتاج حقًا في عام 1995 لإنشاء تصميم قائم على سلسلة نموذج أولي: فهو يوفر الذاكرة لأطول فترة ممكنة! وبشكل عام ، أعتقد أن هذا لا يزال يمكن أن يكون جانبًا مهمًا للغاية.

بناءً على التصميم المشار إليه والرأي القائل " كل شيء كائن " ، يمكننا محاولة استنساخ شيء من هذا القبيل. ولكن ما هو الاستنساخ هنا الآن؟ أعتقد أنه باتباع متطلبات متطلباتنا ، يمكننا أن نفترض شيئًا ما مثل Structural أو Surface Copy ، في شيء مشابه لسابقات Object.assign الحديثة.
لننفذ نسخة هيكلية بسيطة في عام 1995 باستخدام (var i in) {} ، لأن المعيار سمح بالفعل بهذا :

 // back in 1995 cloning // it is not deep clone, // though we might not need deep at all var cloneProps = function (clonedObject, destinationObject) { for (var key in clonedObject) { destinationObject[key] = clonedObject[key]; } }; 

كما ترى ، لا يزال هذا النهج "ناجحًا" ، على الرغم من أنه عمومًا ، بطبيعة الحال ، أوصي بالنظر في الوحدة العميقة للحصول على فهم أكثر تفصيلًا لكيفية عمل الاستنساخ في جافا سكريبت ، ولكن لأغراض المقالة ، فإن التطبيق المتسق مناسب تمامًا لنا وصفها cloneProps ، لأنه يمكننا استخدامها بشكل جيد في تلك العصور القديمة:

  • استنساخ الكائنات باستخدام المُنشئ : باستخدام المُنشئ ، قم بإنشاء استنساخين مختلفين على الأقل

     // cloneProps is described above var SomeConstructor = function (clonedObject) { cloneProps(clonedObject, this); }; var someExistingObjectToClone = { foo : 'bar' }; var clone1 = new SomeConstructor(someExistingObjectToClone); var clone2 = new SomeConstructor(someExistingObjectToClone); // clone1.foo == clone2.foo 
  • استنساخ مُنشئ من مُنشئ: نطبق استخدام سلوك مُنشئ من مُنشئ آخر

     var SomeConstructor = function () { this.a = 'cloned'; }; var AnotherConstructor = function () { // Function.prototype.call // was already invented in 1st ECMA-262 SomeConstructor.call(this); }; 
  • استنساخ مُنشئ باستخدام كائن: سنستخدم نفس الكائن لتنفيذ استنساخ في مُنشئين على الأقل

     var existentObject = { foo : 'bar' }; var SomeConstructor = function () { cloneProps(foo, this); }; var OtherConstructor = function () { cloneProps(foo, this); }; 
  • استنساخ كائن من كائن آخر: استخدم كائنًا واحدًا لإنشاء العديد من الحيوانات المستنسخة الخاصة به . لا يوجد شيء يمكن وصفه هنا ، فقط اعتبره كما cloneProps لدينا من المثال الأول أعلاه.

مع الاستنساخ ، بشكل عام ، كل شيء بسيط ، كما نرى ، كل شيء واضح وبشكل عام ، ولكن ...

هل من السهل بالنسبة لنا أن نفعل ميراث الكيانات ، وذلك باستخدام مزيج من سابقاتها؟

  • وراثة كائن باستخدام Constructor: هذا هو الغرض من المصممين ، وسنعرض فقط كيف تم تصميمه في الأصل .

     var existentObject = { foo : 'bar' }; var SomeConstructor = function () {}; SomeConstructor.prototype = existentObject; var inheritedObject = new SomeConstructor(); // we have no instanceof yet in ECMA 262 of 1995 // therefore we are unable to rely on this window.alert(inheritedObject.foo); // bar 
  • وراثة المنشئ من مُنشئ آخر: لا شك أن أول من لاحظ هذا كان عبقريًا متميزًا. الكل في الكل ، هذا مثال كلاسيكي آخر من كل مكان .

     var FirstConstructor = function () { this.foo = 'bar'; }; var InheritedConstructor = function () { FirstConstructor.call(this); }; InheritedConstructor.prototype = { bar : 'foo' }; InheritedConstructor.prototype.constructor = FirstConstructor; var inherited = new InheritedConstructor(); // { foo : 'bar', bar : 'foo' } 

    سيكون من الممكن ذكر شيء متطور ، لكن لماذا
  • وراثة المنشئ من الكائن: مرة أخرى ، نحن فقط نستخدم .prototype = كائن في كل مرة نحتاج إليها ، لا يوجد شيء لوصف ، نحتاج دائمًا إلى تعيين Constructor.prototype لأنه من المفترض أن نضع الكائن هناك ، ومن خلال رابط ضمني نحصل على جميع خصائصه .
  • وراثة كائن من كائن: نفس الشيء. نحن ببساطة نضع الكائن الأول في Constructor.prototype وبمجرد أن نقول Constructor الجديد ، سنقوم بإنشاء نسخة موروثة حيث ستكون هناك مراجع ضمنية لخصائص الكائن الأول لدينا.

وبالطبع ، في كل هذه المواقف مع الميراث ، ستتاح لنا الفرصة للتحقق باستخدام مثيل من المنشئ الذي أنشأنا الكائنات منه ، على الرغم من أنه ، بالطبع ، يجب الإشارة إلى أن مثيله نفسه ظهر في المعايير بعد أربع سنوات تقريبًا.

صحيح ، بقيت هذه التفاصيل الصغيرة من الفقرة 4.2.1:
تكون قادرة على القيام بذلك لطالما لزم الأمر ، كما يقول:
و هكذا
حسنًا ، دعونا نحاول أن نجعل الميراث لا نهاية له حقًا ، وذلك باستخدام التكنولوجيا منذ عام 1995 .

في الواقع ، دعنا نتخيل أن لدينا كيانين ، وليس كيانات ، ولكن لدينا كائنات بسيطة. وأردنا أن نرث واحدًا من الآخر ، ثم ربما من الآخر ، ومن الآخر ، وهكذا ...

لكن كيف؟


نلقي نظرة أبعد قليلا ، أعمق.
الجواب الصحيح هنا مرة أخرى هو: وراثة ما نحتاج إلى خلق؟

بعد كل شيء ، نحن لسنا بحاجة إلى هذه الكيانات بمفردنا. نحن بحاجة إلى خصائصها: البيانات المرتبطة تستهلك الذاكرة. وأيضًا ، ربما نحتاج إلى بعض السلوك: طرق تستخدم هذه البيانات. وسيكون الأمر صادقًا تمامًا ، إذا كانت لدينا الفرصة للتحقق من أين وأين ورثنا واستخدام ما. بشكل عام ، سيكون الأمر رائعًا تمامًا إذا استطعنا إعادة إنتاج التصميم الموروث لأنماط الوراثة في المستقبل ، مما يعني أنه إذا ورثنا أحدهما عن عدة مرات أخرى ، فسنحصل دائمًا على نفس النتيجة ، وفقًا لما كتبناه (العقد) . على الرغم من أنها لا تزال ، إلا أنه قد يكون من المفيد لنا أن نصلح لحظة الخلق بطريقة أو بأخرى ، لأن كياناتنا "السابقة" يمكن أن تتغير بمرور الوقت ، ولا يزال "الورثة" ، مع منحهم الاحترام في هذا ، يتغيرون معهم قد لا تريد تماما ل.

وبما أن جميع التعليمات البرمجية الخاصة بنا عبارة عن مزيج من البيانات والسلوك ، فهل من الطبيعي عمومًا استخدام نفس الطريقة - الجمع بين البيانات والعرض التقديمي - عند تصميم نظام الوراثة؟

بالنسبة لي ، كل هذا يشبه ما نراه عند مراقبة الحياة بكل أشكالها المذهلة. من أول وحيد الخلية ، إلى متعدد الخلايا وأحفادهم ، وكذلك إلى الحيوانات والشعوب والإنسانية والقبائل والحضارات والفكر وأشكاله المصطنعة ، وكذلك إلى الفضاء ، إلى المجرة ، إلى النجوم! و:
"... كل ما يتعين علينا القيام به هو التأكد من مواصلة الحديث ..."
(كل ما نحتاج إليه هو مواصلة التواصل)

لا يصدق في مدروسه ، مقتبس من ستيفن هوكينج ، شاع في وقت لاحق في هذه التحفة بيند فلويد .

تتيح لك لغات البرمجة المبنية على تمرير الرسائل ومفهوم يستند إلى Flow الذي يتم تنفيذه من خلال واجهة برمجة تطبيقات داخلية قوية الانتقال من البيانات البسيطة إلى التجريدات العليا والوصف وكل شيء آخر. أعتقد أن هذا فن خالص ، وكيف يعمل بشكل خاص في بنى جافا سكريبت المخفية بشدة من خلال العلاقات الضمنية بين البيانات في سلاسل النموذج الأولي.

تخيل مرة أخرى سلفين ، يتواصلان وفي لحظة واحدة تخلق عواطفهم ومشاعرهم طفلًا. يكبر الطفل ، ويلتقي بطفل آخر ، ويتواصل ، ويظهر السليل التالي ، ويواصله ويواصله ... ونحتاج دائمًا إلى والدين ، وإلا فإنه ليس من الطبيعي ، ستكون هندسة الوراثة بالفعل. اثنان ، لا أكثر ولا أقل. يتلقى السليل نفس تراثه ، لذلك فهو بسيط ومفهوم.

أنا أفهم أن الأمر سيبدو غريبًا ، لكن نعم ، لدينا كل ما نحتاجه لإنشاء نموذج الوراثة هذا في عام 1995. وأساس كل ذلك هو بدقة 4.2.1 الكائنات ، والإشارة الضمنية من خلال النموذج الأولي.

وهذا هو بالضبط ، كما هو ، دمج ParentObject مع ParentConstructor عن طريق تحديد .prototype ومن ثم سيخلق Constructor لنا ChildObject ، بالطبع ، إذا قلنا الكلمة السحرية " جديد ":

 var ParentObject = { foo : 'bar' }; var ParentConstructor = function () {}; ParentConstructor.prototype = ParentObject; var ChildObject = new ParentConstructor(); // starting from 1995 and then ECMA 262 // we are able to say new // each time we need a ChildObject 

يمكننا تمييز هنا أسلافنا. في اللحظة التي قلنا فيها الكلمة السحرية " جديد " ، طلبنا منهم الدردشة. إذا لم يرغبوا في التواصل ، فستتوقف الحياة ، وستقع العملية مع وجود خطأ ، وسيقوم المترجم (المترجم) بإخبارنا بذلك.

بالطبع ، نعم ، لكننا طلبنا شجرة الوراثة أو ندعها تبدو أكثر بساطة بكثير ، على الأقل لشجرة الأنساب . والإجابة لا تزال كما هي ... كائننا الفرعي يكبر ، ويصبح كائنًا رئيسيًا ، ثم يلتقي بكائن مُنشئ جديد وبمجرد أن نقول كلمة مطمئنة " جديدة " - السحر:

 // this Assignment is just to show it grew up var ChildObjectGrownToParent = ChildObject; var AnotherConstructor = function () {}; AnotherConstructor.prototype = ChildObjectGrownToParent; var SequentialChildObject = new AnotherConstructor(); // checking Life Cycle ;^) console.log(ChildObject instanceof ParentConstructor); // true console.log(SequentialChildObject instanceof ParentConstructor); // true console.log(SequentialChildObject instanceof AnotherConstructor); // true 

ويمكننا أن نواصل القيام بهذا الإعلان بلا حدود. وأنا ربما أؤمن حقًا أن هذه كانت الفكرة الرئيسية عند تطوير تصميم سلسلة النموذج الأولي ، لأنه كما نعلم جميعًا ، فإن هذا النهج يخلق بعض المشكلات الدقيقة جدًا ولكن ليس أقلها سوءًا ...

1: المجتمع ... كما يمكنك بسهولة التحقق من نفسك ، فإن تحديد ParentConstructor " a أو AnotherConstructor" في .protype هو عقد اجتماعي خطير وصارم للغاية في قبيلة لدينا. يقوم بإنشاء مرجع لخصائص ParentObject ( .foo ) لـ Heirs : ChildObject و SequentialChildObject . وإذا تخلصنا من هذا المؤشر ، فستختفي هذه الروابط. إذا تنافسنا ، وأعدنا تعيين هذه الإشارة إلى كائن آخر ، فإن ورثتنا سيرثون على الفور خصائص أخرى. لذلك ، من خلال الجمع بين الأجداد من خلال .prototype ، ربما يمكننا القول أننا نخلق نوعًا من خلية المجتمع ، لأن هؤلاء "الأسلاف" يمكنهم إنتاج العديد من النسل المتماثل في كل مرة نسألهم فيها باستخدام الجديد . وبالتالي ، بعد تدمير "العائلة" ، فإننا ندمر الصفات الوراثية لأحفاده ، مثل هذه الدراما ؛ ^)

ربما يكون كل هذا هو الحديث عن Legacy في الكود لدينا ، يجب أن نحرص على ذلك عندما سننشئ رمزًا آمنًا ومدعومًا ! بالطبع ، لم تتم مناقشة SOLID و Liskov Principle and Design by Contract و GRASP في عام 1995 ، لكن من الواضح أن هذه المنهجيات لم يتم إنشاؤها "من الصفر" ، فقد بدأ كل شيء في وقت مبكر.

2: العائلة ... يمكننا أن نتحقق بسهولة من أن ParentObject الخاص بنا مسموح به أن يكون تافهاً للغاية مع Constructos الأخرى. هذا ليس عدلاً ، لكن يمكننا استخدام أكبر عدد ممكن من البنائين كما نرغب في الميراث من ParentObject لدينا ، وبالتالي إنشاء العديد من الأسر كما نود. من ناحية أخرى ، يرتبط كل مُنشئ ارتباطًا وثيقًا بـ ParentObject من خلال مهمة .prototype ، وإذا لم نرغب في إلحاق ضرر بالورثة ، فيجب علينا الحفاظ على هذا الاتصال لأطول فترة ممكنة. يمكن أن نسميها فن المأساة في تاريخ قبيلتنا. على الرغم من أن هذا بالطبع يحمينا من فقدان الذاكرة - نسيان ما ورثناه ومنه ، ولماذا يحصل ورثتنا على مثل هذا التراث . وثناءً على Mnemosyne العظيم! ، يمكننا حقًا اختبار شجرة سلسلة النموذج الأولي الخاصة بنا والعثور على قطع أثرية من الخطأ الذي ارتكبناه.

3: الشيخوخة ... من المؤكد أن ParentObject و Constructor لدينا عرضة للضرر خلال دورة حياة برنامجنا. يمكننا محاولة الاعتناء بهذا ، لكن لا أحد في مأمن من الأخطاء. وكل هذه التغييرات يمكن أن تضر الورثة. يجب أن نعتني بتسريبات الذاكرة . بالطبع ، يمكننا تدمير الأجزاء غير الضرورية من الكود في وقت التشغيل وبالتالي تحرير الذاكرة التي لم تعد تُستخدم في دورة حياتنا. بالإضافة إلى ذلك ، يجب أن نتخلص من كل إمكانات إنشاء التناقضات المؤقتة في سلاسل النماذج الأولية ، لأنه في الواقع من السهل جدًا أن يرث الجد من سلالته. ولكن يمكن أن يكون هذا بالفعل خطيرًا للغاية ، لأن مثل هذه الأساليب المتمثلة في التغلب على الماضي من المستقبل يمكن أن تخلق أكوامًا كاملة من منتجات Heisenbags التي يصعب إعادة إنتاجها ، خاصة إذا حاولنا قياس شيء يمكن أن يتغير بحد ذاته بمرور الوقت.

وقائع القرارات


فليكن الأمر بسيطًا وواضحًا وليس مفيدًا للغاية ، ولكن بدلاً من التفكير في مُنشئنا و ParentObject كأم وأبي ، فلنصفهما على أنهما بيض و ... حبوب لقاح . ثم ، في المستقبل ، عندما ننشئ Zygote باستخدام كلمة " جديد " التي تعتز بها ، فلن يحدث أي ضرر لخيالنا!

في اللحظة التي نفعل فيها هذا ، سنتخلص فورًا من المشكلات الثلاثة المذكورة أعلاه! بالطبع ، نحن بحاجة إلى القدرة على إنشاء زيجوتيس أنفسهم ، مما يعني أننا بحاجة إلى "مصنع المصممين". والآن نسميها ما تحب ، أيها الأمهات والآباء ، ما الفرق ، لأن الخلاصة هي أنه إذا كنا سنقول " جديد " ، فيجب علينا إنشاء قفص مصمم "جديد تمامًا" ، ووضع حبوب اللقاح عليه ، وهذا فقط سيسمح لنا لزراعة " تساقط الثلوج " "الجديد" الصحيح في عام 2020 البعيدة والثلجي:

 var Pollen = { season : 'Spring' }; // factory of constructors var FlowersFactory = function (proto) { var FlowerEggCell = function (sort) { this.sort = sort; }; FlowerEggCell.prototype = proto; return FlowerEggCell; }; var FlowerZygote = FlowersFactory(Pollen); var galanthus = new FlowerZygote('Galanthus'); 

( , , , -, ...)

, , . « » , , (. .: , , , bla-bla-bla )…

, , 146% , . , , (. .: , , ).

, , : JavaScript , . , , , FlowerEggCell FlowerEggCellClass FlowersFactory : , instanceof FlowerEggCell FlowerZygote . FlowerZygote , FlowersFactory , , FlowerEggCell FlowerEggCellClass " reference " .

, .prototype null this , . call (null , . apply (null . bind (null code style (. .: Sorrow , , , ).

!

!

V

Source: https://habr.com/ru/post/ar470994/


All Articles