Héritage JavaScript du point de vue d'un nerd ennuyé: Constructors Factory

lampe de lumiÚre et pomme de discorde C'est l'histoire d'une piÚce trÚs spéciale de JavaScript, le langage artificiel le plus utilisé au monde aujourd'hui (2019).

L'article prĂ©sente une sorte de vision philosophique de l'hĂ©ritage en JavaScript, et j'ose seulement espĂ©rer qu'il est basĂ© sur la source de connaissances la plus impressionnante: la vie elle-mĂȘme dans toutes ses manifestations. Je ne sais pas si cela a Ă©tĂ© une inspiration lors de la crĂ©ation de la conception de la chaĂźne prototype en JavaScript.

Mais si c'est le cas, alors il est si important et puissant que lorsque je commence Ă  y penser, il devient parfois mĂȘme difficile de respirer ...

(tous les liens sont soulignés )


Je suis Ă©galement sĂ»r qu’aucun d’entre nous ne doutera que Brendan Ike (Eich) - l’auteur du langage de programmation JavaScript - est un gĂ©nie exceptionnel! Et pas seulement parce qu'il rĂ©pĂšte souvent:
Pariez toujours sur JavaScript!
Commençons! Et notre premier point de départ sera l'Imagination, dans laquelle nous désactiverons d'abord tous les préjugés, omissions et autres effets secondaires.

Nous retournons vers le futur , l'Úre précédant la création de l'Internet moderne au début des années 1990.

Depuis l'époque des premiers pirates qui ont inventé tout ce que nous ( les employés informatiques ) utilisons maintenant, nous sommes passés à un croquis impressionnant: à propos de la guerre entre les navigateurs Netstcape Navigator 2 et Internet Explorer 3. Java vient de sortir, et presque tout de l'Internet moderne n'a pas encore été inventé ou pas pré-ouvert. Il est possible que, comme moi, dans ce «bon vieux temps», vous étiez jeune et que vous vous souveniez de ce merveilleux sentiment d'implication dans toute la splendeur qui se crée sous vos yeux.

Donc, vous avez un PC trĂšs puissant sur le plus moderne Intell Pentium 200 MMX avec 32 Mo de RAM, Windows 3.11 ou mĂȘme Windows 95 et vous envisagez l'avenir avec espoir! Et, bien sĂ»r, les deux navigateurs sont Ă©galement installĂ©s. Vous avez un accĂšs commutĂ© , Ă  travers lequel vous vous connectez au rĂ©seau pour de nouvelles ordures, aussi, pour Ă©tudier ou simplement discuter, discuter. Bien que vous ne puissiez toujours pas discuter directement dans le navigateur, vous utilisez probablement des systĂšmes de livraison de messages diffĂ©rĂ©s, quelque chose comme EMail ou peut-ĂȘtre UseNet , ou, trĂšs probablement, vous avez dĂ©jĂ  maĂźtrisĂ© la livraison instantanĂ©e via IRC .

Quelques annĂ©es s'Ă©coulent et TOUT change littĂ©ralement ... Soudain, vous regardez l'animation de flocons de neige sur les pages Web pour vous fĂ©liciter pour le Nouvel An et NoĂ«l. Bien sĂ»r, vous ĂȘtes intĂ©ressĂ© par la façon dont cela se fait, et vous dĂ©couvrez un nouveau langage - JavaScript. Puisque le HTML n'est pas nouveau pour vous, vous commencez Ă  apprendre ce techno-mĂ©tier sĂ©duisant. BientĂŽt, vous dĂ©couvrez CSS et il s'avĂšre que c'est Ă©galement important, car tout est maintenant fait Ă  partir d'une combinaison de ces trois: HTML, JavaSript et CSS. Ouah.

À peu prĂšs Ă  la mĂȘme Ă©poque, vous remarquerez peut-ĂȘtre quelques grandes choses dans Windows lui-mĂȘme, CScript et HTA y sont apparus, et mĂȘme alors, il est devenu possible de crĂ©er des applications de bureau Ă  part entiĂšre directement sur JS (et cela fonctionne toujours).

Et vous avez donc commencĂ© Ă  crĂ©er votre premier serveur Web, peut-ĂȘtre en Perl ou en C ~ C ++ . Peut-ĂȘtre mĂȘme que vous avez commencĂ© Ă  utiliser des systĂšmes d' exploitation de type Unix et Ă  le faire sur bash . Et tout cela "spin-spinning" grĂące Ă  la Common Gateway Interface (ne le confondez pas avec cet autre CGI ). PHP n'existe presque toujours pas, mais vous l'aimerez peut-ĂȘtre bientĂŽt.

Ère 200x. Vous faites maintenant ASP en JScript . Ceci est trĂšs similaire au JavaScript qui fonctionne Ă  l'intĂ©rieur de vos pages Web. C'est trop cool! Vous envisagez de crĂ©er votre propre moteur de modĂšle , une sorte de parodie de XML . Et soudain, quelqu'un appelle AJAX toutes ces façons amusantes de charger dynamiquement du contenu que vous utilisez depuis plusieurs annĂ©es. Et tous pensent maintenant qu'il n'y a que XMLHTTPRequest , mais vous vous souvenez que les donnĂ©es peuvent ĂȘtre transfĂ©rĂ©es vers BMP , IFrame ou mĂȘme en insĂ©rant la balise <script> . Et puis quelqu'un parle soudainement avec enthousiasme de JSON et de son utilitĂ©, lorsque vous avez conduit des donnĂ©es pendant une Ă©ternitĂ© avec quelque chose comme ceci:

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

Ce n'est pas grave maintenant , mais vous pouvez toujours vous rappeler comment ...

Lorsque vous reprenez vos esprits, de temps en temps, vous commencez Ă  vous retrouver Ă  fouiner avec Rhino ou Nashorn pour tenter de satisfaire les souhaits des clients Java en utilisant Alfresco ou Asterisk . Et vous avez dĂ©jĂ  entendu parler de l'avĂšnement imminent de JavaScript dans le monde des micropuces, et vous ĂȘtes trĂšs inspirĂ© par cette nouvelle. Et bien sĂ»r, vous avez maintenant jQuery et Backbone .

En observant les chutes de neige de l'annĂ©e 2010 Ă  venir, vous savez dĂ©jĂ  que dans votre monde toutes les rĂšgles du jeu vont bientĂŽt changer, car «Player No. 1» est entrĂ© dans le champ: Node.js. Et les 10 prochaines annĂ©es, vous passerez avec ce nouveau jouet, et mĂȘme maintenant, en 2019, vous ne pouvez toujours pas en avoir assez de la fraĂźcheur.

En gĂ©nĂ©ral, vous ĂȘtes satisfait de tout, tout vous convient, tous ces jouets et jeux en eux constituent une grande partie de vos intĂ©rĂȘts de vie.

Mais il y a une petite question que vous vous posez jour aprÚs jour, nuit aprÚs nuit depuis deux décennies maintenant:

Si vous deviez le faire, comment expliqueriez-vous Empathy en utilisant JavaScript?


Vous savez que l'un des sujets les plus compliquĂ©s de JavaScript est l' hĂ©ritage de prototypes et la chaĂźne de prototypes . Et vous aimez ce sujet, vous pouvez expliquer comment tout cela fonctionne et fonctionne, tout simplement parce que vous l'avez appris presque dĂšs le dĂ©but, avant mĂȘme la naissance de la premiĂšre version de la norme , et oĂč, comme vous vous en souvenez, il y en a 4,2 .1 Objets :
ECMAScript prend en charge l'héritage basé sur un prototype. Chaque constructeur a un prototype associé, et chaque objet créé par ce constructeur a une référence implicite au prototype (appelé prototype de l'objet) associé à son constructeur. En outre, un prototype peut avoir une référence implicite non nulle à son prototype, etc. c'est ce qu'on appelle la chaßne prototype .
Chaque objet est créé avec une référence implicite au prototype. C'est ce qu'on appelle la chaßne d'héritage du prototype, que vous pouvez continuer aussi longtemps que vous le souhaitez.

Wow ... Et si tout Ă  coup, comme moi, vous pensez peut-ĂȘtre que c'est l'une des plus grandes inventions de la science informatique , comment exprimeriez-vous l'effet que la lecture de cette dĂ©claration a eu sur vous?

Revenons au dĂ©but. Dans la cour 1995. Vous ĂȘtes Brendan Ike et vous devez inventer un nouveau langage de programmation. Peut-ĂȘtre que vous aimez Lisp ou Scheme , au moins certaines de leurs parties prĂ©fĂ©rĂ©es. Et vous ĂȘtes confrontĂ© Ă  la nĂ©cessitĂ© de rĂ©soudre le problĂšme de l' hĂ©ritage , car vous devez prĂ©tendre que le langage a une certaine implĂ©mentation de la POO . RĂ©flĂ©chissons : vous devez mĂ©langer toutes les choses que vous aimez, peut-ĂȘtre aussi certaines choses que vous n'aimez pas, et le cocktail rĂ©sultant devrait ĂȘtre assez bon pour que personne ne remarque un truc jusqu'Ă  ce qu'il y ait un rĂ©el besoin de comprendre comment c'est disposĂ© Ă  l'intĂ©rieur.

Et maintenant, la question est: qu'arriverait-il à l'héritage?

Revenons un instant à la réalité. Que savons-nous tous de l'héritage? Quelques réponses évidentes à cette question:

  1. La plupart des formes vivantes sont basĂ©es sur le gĂ©nome . Il s'agit d'un tel rĂ©fĂ©rentiel d'informations sur les caractĂ©ristiques probables et le comportement prĂ©sumĂ© des ĂȘtres vivants. Lorsque vous ĂȘtes une crĂ©ature vivante, vous portez une partie du gĂ©nome en vous, vous pouvez le distribuer, mais vous l'avez reçu des gĂ©nĂ©rations prĂ©cĂ©dentes.
  2. Vous pouvez crĂ©er une crĂ©ature vivante en utilisant deux techniques: mĂ©langer (gĂ©nomes) de deux ancĂȘtres ou, Ă©ventuellement, utiliser le clonage monoĂŻque de l' un d'eux. Bien sĂ»r, aujourd'hui, nous sommes des technologies disponibles qui permettent de mĂ©langer les gĂ©nomes de plus d'une crĂ©ature, mais cela est beaucoup moins Ă©vident et moins naturel.
  3. Le facteur temps est important. S'il n'y a pas de propriĂ©tĂ© hĂ©ritĂ©e, ou pas dĂ©jĂ , alors notre seule issue est de la crĂ©er Ă  partir de zĂ©ro. En plus de cela, il y a aussi l'hĂ©ritage, ce qui passe Ă  l'ĂȘtre de ses ancĂȘtres non pas Ă  travers le gĂ©nome, mais Ă  travers les lois de la propriĂ©tĂ©, et cela peut aussi ĂȘtre significatif.

Pour en revenir au passé, et la bonne question que nous devons nous poser est maintenant: Et, en fait, l'héritage Que voulons-nous obtenir?

Eh bien, en tout cas, dans le processus de résolution du problÚme de l'héritage, nous devons au moins combler le fossé entre la programmation et la vie réelle, sinon, en général, nous n'aurons pas le droit de l'appeler héritage.

Finissons-en maintenant: nous sommes dans les annĂ©es 1995, nous avons le PC le plus puissant avec seulement 32 mĂ©gaoctets de RAM, et nous essayons de crĂ©er un langage interprĂ©tĂ©, nous devons donc prendre grand soin de cette mĂ©moire. Chaque Ă©lĂ©ment de donnĂ©es, en particulier les objets String , consomme beaucoup de mĂ©moire, et nous devrions ĂȘtre en mesure de dĂ©clarer cet Ă©lĂ©ment une seule fois, et dans la mesure du possible Ă  l'avenir, n'utilisez que des pointeurs vers la zone de mĂ©moire occupĂ©e par cet Ă©lĂ©ment. Nous rĂ©sumons: une question trĂšs difficile.

Il y a une opinion populaire: " JavaScript est crĂ©Ă© Ă  partir d'objets ." En utilisant cette trivialitĂ©, nous pouvons trĂšs facilement rĂ©pondre Ă  la question « de quoi » hĂ©riter et « quoi »: d'Objets en Objets. Pour des raisons d'Ă©conomie de mĂ©moire, il s'avĂšre que toutes les donnĂ©es doivent ĂȘtre stockĂ©es dans ces objets, et tous ces liens vers les donnĂ©es doivent Ă©galement ĂȘtre stockĂ©s dans les propriĂ©tĂ©s hĂ©ritĂ©es de ces objets. Peut-ĂȘtre que maintenant, il est clair pourquoi en 1995 nous avions vraiment besoin de crĂ©er un design basĂ© sur une chaĂźne de prototype: il Ă©conomise la mĂ©moire le plus longtemps possible! Et en gĂ©nĂ©ral, je pense que cela peut encore ĂȘtre un aspect trĂšs important.

Sur la base du design indiqué et de l'avis « tout est un objet », nous pouvons essayer de cloner quelque chose comme ça. Mais qu'est-ce que le clonage ici maintenant? Je pense qu'en suivant les exigences de nos exigences, nous pouvons supposer quelque chose comme Structural ou Surface Copy , quelque chose de similaire aux prédécesseurs de Object.assign moderne.
Implémentons une simple copie structurelle en 1995 en utilisant for (var i in) {} , car la norme le permettait déjà :

 // 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]; } }; 

Comme vous pouvez le voir, cette approche "fonctionne" toujours, bien qu'en général, bien sûr, je recommanderais de regarder le module approfondi pour une compréhension plus détaillée de la façon de faire du clonage en JavaScript, mais pour les besoins de l'article, une application cohérente nous convient tout à fait. décrit par cloneProps , car nous pourrions bien l'utiliser dans ces temps anciens:

  • clonage d'objets Ă  l'aide du constructeur: Ă  l'aide du constructeur, crĂ©ez au moins deux clones diffĂ©rents

     // 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 
  • clonage d'un constructeur Ă  partir d'un constructeur: nous implĂ©mentons l'utilisation du comportement d'un constructeur Ă  partir d'un autre constructeur

     var SomeConstructor = function () { this.a = 'cloned'; }; var AnotherConstructor = function () { // Function.prototype.call // was already invented in 1st ECMA-262 SomeConstructor.call(this); }; 
  • clonage d'un constructeur Ă  l'aide d'un objet: nous utiliserons le mĂȘme objet pour implĂ©menter le clonage dans au moins deux constructeurs

     var existentObject = { foo : 'bar' }; var SomeConstructor = function () { cloneProps(foo, this); }; var OtherConstructor = function () { cloneProps(foo, this); }; 
  • clonage d'un objet Ă  partir d'un autre objet: utilisez un objet pour crĂ©er plusieurs de ses clones . Il n'y a rien Ă  dĂ©crire ici, prenez-le comme nos cloneProps du premier exemple ci-dessus.

Avec le clonage, en général, tout est simple, comme on le voit, tout est clair et en général, mais ...

Est-il si facile pour nous de faire l'héritage des entités, en utilisant une combinaison de leurs prédécesseurs?

  • HĂ©ritage d'un objet Ă  l'aide du constructeur: c'est le but mĂȘme des concepteurs, nous allons simplement montrer comment il a Ă©tĂ© initialement conçu .

     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 
  • HĂ©ritage du constructeur d'un autre constructeur: sans aucun doute, le premier qui a remarquĂ© que c'Ă©tait un gĂ©nie exceptionnel. Dans l'ensemble, c'est un autre exemple classique de partout .

     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' } 

    il serait possible de dire quelque chose de sophistiqué, mais pourquoi
  • HĂ©ritage du constructeur de l'objet: encore une fois, nous utilisons simplement .prototype = object chaque fois que nous en avons besoin, il n'y a rien Ă  dĂ©crire, nous devons toujours assigner Constructor.prototype car il est censĂ© y placer l'objet, et par un lien implicite nous obtenons toutes ses propriĂ©tĂ©s .
  • HĂ©riter d'un objet d'un objet: la mĂȘme chose. Nous plaçons simplement le premier objet dans Constructor.prototype et dĂšs que nous disons nouveau constructeur, nous crĂ©erons une copie hĂ©ritĂ©e dans laquelle il y aura des rĂ©fĂ©rences implicites aux propriĂ©tĂ©s de notre premier objet.

Et bien sĂ»r, dans toutes ces situations avec hĂ©ritage, nous aurons l'occasion de vĂ©rifier en utilisant instanceof Ă  partir de quel constructeur nous avons crĂ©Ă© les objets, bien que, bien sĂ»r, il convient de noter que instanceof lui-mĂȘme est apparu dans les normes prĂšs de quatre ans plus tard.

Certes, il restait un si petit détail du paragraphe 4.2.1:
ĂȘtre en mesure de le faire aussi longtemps que nĂ©cessaire, comme il est dit:
et ainsi de suite
Eh bien, essayons de rendre l'héritage vraiment sans fin , en utilisant la technologie de 1995 .

En fait, imaginons que nous avons deux EntitĂ©s, et non des Constructeurs, mais des objets simples. Et nous voulions hĂ©riter l'un de l'autre, et puis peut-ĂȘtre de l'autre, et de l'autre, et ainsi de suite ...

Mais comment?


Jetez un Ɠil un peu plus loin, plus profondĂ©ment.
Ici encore, la bonne réponse est: l' héritage de ce que nous devons créer?

AprĂšs tout, nous n'avons pas besoin de ces entitĂ©s par nous-mĂȘmes. Nous avons besoin de leurs propriĂ©tĂ©s: donnĂ©es associĂ©es consommant de la mĂ©moire; et aussi, nous avons probablement besoin d'un certain comportement: des mĂ©thodes utilisant ces donnĂ©es. Et ce sera tout aussi honnĂȘte , si nous avons la possibilitĂ© de vĂ©rifier oĂč et oĂč nous avons hĂ©ritĂ© et en utilisant quoi. En gĂ©nĂ©ral, ce serait tout aussi cool si nous pouvions reproduire la conception inhĂ©rente des modĂšles d'hĂ©ritage Ă  l'avenir, ce qui implique que si nous hĂ©ritons l'un de l'autre plusieurs fois, nous obtiendrons toujours le mĂȘme rĂ©sultat, selon ce que nous avons Ă©crit (contrat) . Bien que ce soit encore, il peut ĂȘtre tout aussi utile pour nous de fixer en quelque sorte le moment de la crĂ©ation, car nos entitĂ©s "prĂ©cĂ©dentes" peuvent changer avec le temps, et les "hĂ©ritiers", en leur donnant du respect en cela, changent toujours avec eux pourrait bien ne pas vouloir.

Et, puisque tout notre code est une combinaison de donnĂ©es et de comportement, est-il gĂ©nĂ©ralement normal d'utiliser la mĂȘme mĂ©thode - combinant donnĂ©es et prĂ©sentation - lors de la conception d'un systĂšme d'hĂ©ritage?

Quant Ă  moi, tout cela ressemble Ă  ce que nous voyons en observant la vie sous toutes ses formes incroyables. Du premier unicellulaire au multicellulaire et Ă  leurs descendants, et plus loin aux animaux, aux gens, Ă  l'humanisme et aux tribus, aux civilisations, Ă  l'intellect et Ă  ses formes artificielles, et plus loin Ă  l'espace, Ă  la galaxie, aux Ă©toiles! et:
"... Tout ce que nous devons faire, c'est nous assurer de continuer Ă  parler ..."
(tout ce que nous devons faire est de continuer la communication)

Incroyable dans sa prĂ©venance, une citation de Stephen Hawking , par la suite popularisĂ©e dans ce chef-d'Ɠuvre de Pind Floyd .

Les langages de programmation basés sur le passage de messages et un concept basé sur Flow implémenté via une API interne robuste vous permettent de passer de données simples à des abstractions, des descriptions et tout le reste. Je pense que c'est de l'Art pur, et comment cela fonctionne en particulier dans les structures JavaScript profondément cachées à travers des relations implicites entre les données dans les chaßnes de prototypes.

Imaginez Ă  nouveau deux ancĂȘtres, ils communiquent et Ă  un moment leurs Ă©motions et leurs sentiments crĂ©ent un enfant. L'enfant grandit, rencontre un autre enfant, ils communiquent et le prochain descendant apparaĂźt, et ainsi de suite ... Et nous avons toujours besoin de deux parents, sinon ce n'est pas naturel, ce sera dĂ©jĂ  du gĂ©nie gĂ©nĂ©tique. Deux, ni plus ni moins. Un descendant reçoit la mĂȘme chose que son hĂ©ritage, c'est donc simple et comprĂ©hensible.

Je comprends que cela puisse sembler étrange, mais oui, nous avons tout ce dont nous avons besoin pour créer ce modÚle d'héritage en 1995. Et la base de tout cela est précisément 4.2.1 Objets , référencement implicite via prototype.

Et c'est exactement comme ça, en combinant ParentObject avec ParentConstructor en spécifiant .prototype puis Constructor va probablement nous créer un ChildObject , bien sûr, si nous disons le mot magique " nouveau ":

 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 

Nous pouvons discerner ici nos deux ancĂȘtres. Au moment oĂč nous avons dit le mot magique " nouveau ", nous leur avons demandĂ© de discuter. S'ils ne veulent pas communiquer, Life s'arrĂȘtera, le processus tombera avec une erreur et le compilateur (interprĂšte) nous en parlera.

Bien sĂ»r, oui, mais nous avons demandĂ© l’ arbre d’hĂ©ritage ou l’avons laissĂ© ĂȘtre beaucoup plus simple, du moins pour l’arbre gĂ©nĂ©alogique . Et la rĂ©ponse est toujours la mĂȘme ... notre objet enfant grandit, et il devient un objet parent , puis il rencontre un nouvel objet constructeur et dĂšs que nous disons le mot convoitĂ© " nouveau " - magie:

 // 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 

Et nous pouvons continuer Ă  le faire Ă  l'infini. Et je crois peut-ĂȘtre vraiment que c'Ă©tait l'idĂ©e principale lors du dĂ©veloppement de la conception de la chaĂźne de prototypes, car comme nous le savons tous, cette approche crĂ©e des problĂšmes trĂšs soignĂ©s mais non moins dĂ©sagrĂ©ables ...

1: CommunautĂ© ... Comme vous pouvez facilement le vĂ©rifier par vous-mĂȘme, spĂ©cifier dans .prototype ParentConstructor ' a ou AnotherConstructor' a est un contrat social trĂšs sĂ©rieux et strict dans notre tribu. Il crĂ©e une rĂ©fĂ©rence aux propriĂ©tĂ©s ParentObject ( .foo ) pour les hĂ©ritiers: ChildObject et SequentialChildObject . Et si nous nous dĂ©barrassons de cette indication, ces liens disparaĂźtront. Si nous inventons et rĂ©affectons cette rĂ©fĂ©rence Ă  un autre objet, nos hĂ©ritiers hĂ©riteront instantanĂ©ment d'autres propriĂ©tĂ©s. Par consĂ©quent, en combinant les ancĂȘtres Ă  travers .prototype , nous pourrions probablement dire que nous crĂ©ons une sorte de cellule de la sociĂ©tĂ© , parce que ces «ancĂȘtres» peuvent reproduire de nombreux descendants identiques chaque fois que nous leur en parlons en utilisant new . Et ainsi, ayant dĂ©truit la "famille", nous ruinons les qualitĂ©s hĂ©rĂ©ditaires de ses descendants, un tel drame; ^)

Peut-ĂȘtre que tout cela parle d' HĂ©ritage dans notre code, nous devons nous en occuper lorsque nous allons crĂ©er un code sĂ»r et pris en charge ! Bien sĂ»r, aucun SOLID , principe de Liskov et conception par contrat et GRASP n'ont Ă©tĂ© discutĂ©s en 1995, mais il est Ă©vident que ces mĂ©thodologies n'ont pas Ă©tĂ© crĂ©Ă©es «à partir de zĂ©ro», tout a commencĂ© bien plus tĂŽt.

2: Famille ... Nous pouvons facilement vĂ©rifier que notre ParentObject peut ĂȘtre trĂšs frivole avec d'autres Constructos. Ce n'est pas juste, mais nous pouvons utiliser autant de constructeurs que nous le souhaitons dans l'hĂ©ritage de notre ParentObject et ainsi crĂ©er autant de familles que nous le souhaitons. D'un autre cĂŽtĂ©, chaque constructeur est trĂšs Ă©troitement associĂ© Ă  ParentObject Ă  travers la tĂąche .prototype, et si nous ne voulons pas nuire Ă  nos hĂ©ritiers, nous devons maintenir cette connexion aussi longtemps que possible. Nous pourrions l'appeler l'art de la tragĂ©die dans l'histoire de notre tribu. Bien que, bien sĂ»r, cela nous protĂšge de l'amnĂ©sie - l'oubli de ce dont nous avons hĂ©ritĂ© et de qui, et pourquoi nos hĂ©ritiers obtiennent un tel hĂ©ritage . Et, en faisant l'Ă©loge du grand Mnemosyne !, Nous pouvons vraiment facilement tester notre arbre de chaĂźne de prototype et trouver des artefacts de ce que nous avons fait de mal.

3: Vieillesse ... Notre ParentObject et Constructor sont certainement susceptibles d'ĂȘtre endommagĂ©s pendant le cycle de vie de notre programme. Nous pouvons essayer de nous en occuper, mais personne n'est Ă  l'abri des erreurs. Et tous ces changements peuvent nuire aux hĂ©ritiers. Nous devons prendre soin des fuites de mĂ©moire . Bien sĂ»r, nous pouvons trĂšs bien dĂ©truire les parties inutiles du code lors de l'exĂ©cution et ainsi libĂ©rer de la mĂ©moire qui n'est plus utilisĂ©e dans notre cycle de vie . De plus, nous devons nous dĂ©barrasser de toutes les possibilitĂ©s de crĂ©er des Paradoxes Temporaires dans les chaĂźnes de prototypes, car en fait il est assez simple d'hĂ©riter l'AncĂȘtre de son propre Descendant. Mais cela peut dĂ©jĂ  ĂȘtre trĂšs dangereux, car de telles techniques de flirt avec le passĂ© du futur peuvent crĂ©er des tas entiers de Heisenbags difficiles Ă  reproduire, surtout si nous essayons de mesurer quelque chose qui peut lui-mĂȘme changer avec le temps.

Chronique des décisions


Que ce soit simple, Ă©vident et pas trĂšs utile, mais au lieu de penser Ă  notre constructeur et ParentObject comme maman et papa, dĂ©crivons-les comme un Ɠuf et ... du pollen . Ensuite, Ă  l'avenir, lorsque nous crĂ©erons le Zygote en utilisant le mot prĂ©cieux " nouveau ", cela ne fera plus de mal Ă  notre imagination!

DĂšs que nous ferons cela, nous nous dĂ©barrasserons immĂ©diatement des trois problĂšmes ci-dessus! Bien sĂ»r, pour cela, nous avons besoin de pouvoir crĂ©er les zygotes eux-mĂȘmes, ce qui signifie que nous avons besoin de la Factory of Designers. Et maintenant, appelez-le comme vous voulez, mĂšres, pĂšres, quelle diffĂ©rence cela fait-il, car en fin de compte, si nous voulons dire " nouveau ", nous devons crĂ©er une "toute nouvelle" cage de crĂ©ateur de fleurs, y mettre du pollen, et seulement cela nous permettra pour faire pousser un nouveau «bon» Snowdrop dans le lointain et si enneigĂ© 2020m:

 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'); 

(et oui, n'oubliez pas de vérifier la saison avec ce perce-neige, sinon les flocons de neige tomberaient ou tomberaient, et un perce-neige serait une fleur de printemps ...)

Bien sûr, la complexité cyclomatique des décisions que vous essayez de créer en utilisant cette approche sera assez comparable à l' énigme Einstein . Par conséquent, ici j'ai «concocté» une bibliothÚque , cela peut aider à la création de chaßnes de designers et à la mémorisation , (ndlr: bien, takoe, prenez une tarte sur une étagÚre, bla-bla-bla ) ...

Et bien que je ne puisse pas le prouver, cette approche a Ă©tĂ© utilisĂ©e avec succĂšs de temps en temps pendant deux dĂ©cennies maintenant, si vous devez ĂȘtre sĂ»r Ă  146% que tout est normal avec l'hĂ©ritage. Vous pouvez facilement constater par vous-mĂȘme qu'il est Ă©lĂ©mentairement testĂ©, reproduit et pris en charge (NDLR: oui, en ce moment, vous avez tout quittĂ© et vous ĂȘtes allĂ© vous en assurer ).

Bien sĂ»r, ce n'est pas toute l'histoire, nous avons simplement dĂ©clarĂ© le fait: JavaScript est suffisamment bien conçu pour dĂ©crire le graphique de gĂ©nĂ©alogie directement via l'hĂ©ritage. Bien sĂ»r, ici, nous n'avons pas abordĂ© sournoisement le sujet de la dĂ©gradation des classes , mais je suis sĂ»r que vous pouvez vous-mĂȘme facilement remplacer FlowerEggCell par FlowerEggCellClass dans FlowersFactory: l'essence restera la mĂȘme si vous voulez vĂ©rifier vos fleurs par exemple, vous verrez qu'ils sont tous des descendants de FlowerEggCell auxquels vous vous rĂ©fĂ©rez via FlowerZygote . Et bien sĂ»r, vous pouvez maintenant modifier les propriĂ©tĂ©s de FlowerZygote lui - mĂȘme , car cela ne nuira pas Ă  FlowersFactory lui - mĂȘme , il restera capable de crĂ©er d'autres constructeurs FlowerEggCell ou FlowerEggCellClass Ă  l'avenir selon la conception originale de " rĂ©fĂ©rence " que vous y avez mise .

J'espÚre que cet article a dissipé tous les doutes sur l'importance du mot .prototype la prochaine fois que vous verrez null this , . call (null , . apply (null . bind (null code style (. .: Sorrow , , , ).

!

!

V

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


All Articles