Alcuni linguaggi sono abbastanza statici e consentono solo la specifica della relazione di ereditarietà tra due classi al momento della definizione di tali classi. Per C ++, il tempo di definizione è praticamente uguale al tempo di compilazione. (È leggermente diverso in Java e C #, ma non molto.) Altri linguaggi consentono una riconfigurazione molto più dinamica della relazione tra classi (e oggetti di classe in Javascript) tra loro; alcuni consentono di modificare la classe di un oggetto esistente o di modificare la superclasse di una classe. (Questo può causare un totale caos logico, ma può anche modellare abbastanza bene i nasties del mondo reale.)
Ma è importante contrapporre questo alla composizione, dove la relazione tra un oggetto e l'altro non è definita dalla loro relazione di classe (cioè, il loro tipo ) ma piuttosto dai riferimenti che ognuno ha in relazione con l'altro. La composizione generale è un metodo molto potente e onnipresente di organizzazione degli oggetti: quando un oggetto ha bisogno di sapere qualcosa su un altro, ha un riferimento a quell'altro oggetto e invoca metodi su di esso quando necessario. Non appena inizi a cercare questo pattern super-fondamentale , lo troverai assolutamente ovunque; l'unico modo per evitarlo è mettere tutto in un oggetto, il che sarebbe enormemente stupido!
(C'è anche una composizione / aggregazione UML più rigida, ma non è quello di cui parla il libro GoF.)
Una delle cose della relazione di composizione è che gli oggetti particolari non hanno bisogno di essere strettamente legati l'uno all'altro. Lo schema degli oggetti concreti è molto flessibile, anche in linguaggi molto statici come il C ++. (C'è un lato positivo nell'avere cose molto statiche: è possibile analizzare il codice più da vicino e - almeno potenzialmente - emettere un codice migliore con meno overhead).
Per riassumere, Javascript, come con molti altri linguaggi dinamici, può far finta che non usi affatto la compilazione; solo finzione, ovviamente, ma il modello linguistico fondamentale non richiede la trasformazione in un formato intermedio fisso (ad es. un "eseguibile binario su disco"). Questa compilazione viene eseguita in fase di esecuzione e può essere facilmente ripristinata se le cose cambiano troppo. (La cosa affascinante è che un buon lavoro di compilazione può essere fatto, anche partendo da una base molto dinamica ...)
Alcuni pattern GoF hanno davvero senso solo nel contesto di un linguaggio in cui le cose sono abbastanza statiche. Va bene; significa semplicemente che non tutte le forze che influenzano il modello sono necessariamente elencate. Uno dei punti chiave sullo studio dei modelli è che ci aiuta a essere consapevoli di queste importanti differenze e avvertimenti. (Gli altri schemi sono più universali. Tieni gli occhi aperti per quelli.)