To favor composition over inheritance was taken from the Erich Gamma book, Design Patterns. It might be on page 20 or so, it was in reference to Java development, I believe.
Nonetheless, people in the JavaScript community have latched onto this phrase and used it as a selling point to say hey we should favor object composition.
Here is the issue, this is probably the most misunderstood statement ever, in the JavaScript community. Now the statement itself is correct, the author themselves go on to give a very strong argument for saying we should favor object composition, the issue is that if you go on to Google right now and search for JavaScript composition versus inheritance and view all these different blogposts and videos, if you read them, you will find that their definition of composition is 100% incorrect.
So maybe composition versus inheritance is some debatable topic, the issue is that everyone’s understanding of the word composition in the Javascript world is just plain wrong.
So my goal here is to help you understand what the authors of the book were talking about when they wrote that statement and what the people who are writing all these blogposts are talking about when they are writing about composition and my goal here is not to shame anyone in the JavaScript community, that’s not what I am here to do.
I am just trying to make clear that we really messed up the definition of composition and its important for us to correct that understanding and correct that definition, otherwise, we got tons of engineers who are going to be writing really weird code because they think these authors, the authors of this book Design Patterns: Elements of Reusable Object-Oriented Software that I am going to take a look at, were saying one thing, when in fact they were saying a very different other thing.
So, let's get to it.
I am going to first take a look at the book, get an understanding of their definition of composition, then take a look at a blog post and get the blog post definition of composition and compare and contrast the two and I think you will find they are extremely different definitions of composition.
Inside of Design Patterns, a book that was written many years ago, it was not written specifically for JavaScript, I will go down to page 40 or so and it says here very clearly:
Favor object composition over class inheritance
and again this is the phrase that gets repeated hundreds of times.
So let's take a look at this books definition of what composition is.
I am going to scroll down just a bit to the next section which is about Delegation and they are saying the delegation pattern is one way of making composition a very strong pattern, the exact quote is:
Delegation is a way of making composition as powerful for reuse as inheritance [Lie86,JZ911. In delegation, two objects are involved in handling a request: a receiving object delegates operations to its delegate. This is analogous to subclasses deferring requests to parent classes. But with inheritance, an inherited operation can always refer to the receiving object through the this member variable in C++ and self in Smalltalk. To achieve the same effect with delegation, the receiver passes itself
to the delegate to let the delegated operation refer to the receiver.
So delegation is kind of like a tool or method of implementing composition.
They go on to describe exactly how delegation works. So let’s take a look at their example of how delegation works here. They are saying instead of making a Window a subclass of rectangle, just because the window happens to be rectangular, the Window class might instead reuse the rectangle, and here is the really important part, keeping a reference to the rectangle instance variable and delegating Rectangle specific behavior to it.
For example, instead of making class Window a subclass of Rectangle (because windows happen to be rectangular), the Window class might reuse the behavior of Rectangle by keeping a Rectangle instance variable and delegating Rectangle-specific behavior to it. In other words, instead of a Window being a Rectangle, it would have a Rectangle. Window must now forward requests to its Rectangle instance explicitly, whereas before it would have inherited those operations.
So a Window should have a reference to a Rectangle and they offer a diagram in their book, but I recreated it here:

So I said that a Window should have a reference to a Rectangle or generally some kind of shaped object and I can easily swap that object out and that’s how we get code reuse.
SO when the book talks about composition, they are saying, very specifically, we are going to favor delegation as a pattern to implement composition. With this pattern we have some class that has a reference to another object and anytime some request comes in to get the area of the window, the Window class will delegate that calculation off to the outside object.
So that is what the book is saying when it talks about composition.
Let's take a look at an example blogpost where they get it wrong:
const canCast = (state) => ({
cast: (spell) => {
console.log(`${state.name} casts ${spell}!`);
state.mana--;
}
})
const canFight = (state) => ({
fight: () => {
console.log(`${state.name} slashes at the foe!`);
state.stamina--;
}
})
const fighter = (name) => {
let state = {
name,
health: 100,
stamina: 100
}
return Object.assign(state, canFight(state));
}
const mage = (name) => {
let state = {
name,
health: 100,
mana: 100
}
return Object.assign(state, canCast(state));
}
scorcher = mage('Scorcher')
scorcher.cast('fireball'); // Scorcher casts fireball!
console.log(scorcher.mana) // 99
slasher = fighter('Slasher')
slasher.fight(); // Slasher slashes at the foe!
console.log(slasher.stamina) // 99
Again, I am not trying to shame anyone, just trying to clarify a misunderstanding.
So in the above example, the original author of this code is creating a function here called fighter
.
Then inside of fighter, whenever they call it they are going to create an object that they call state and state has some different properties that describe a fighter.
Now a fighter needs to have some number of methods attached to it to actually make this object useful. So here, they are saying Object.assign()
like so:
const fighter = (name) => {
let state = {
name,
health: 100,
stamina: 100
}
return Object.assign(state, canFight(state));
}
Object.assign()
is going to take all the different properties out of this object canFight(state)
and essentially copy paste them over to this object, state
.
Does this not sound a lot like inheritance?
Yes, it kind of does, let's keep that in mind.
So, obviously, we need to understand what canFight()
does right here.
canFight
is defined right here:
const canFight = (state) => ({
fight: () => {
console.log(`${state.name} slashes at the foe!`);
state.stamina--;
}
})
So they pass in that state
object that has all their instance variables tied to it.
And then inside of canFight
all they are doing is returning an object that has some different methods attached to it and the idea is that these methods right here are going to attempt to work on those instance properties like name
, stamina
, health
and so on.
So when these authors of blogposts are talking about composition they are using the literal definition of composition as found in the English dictionary.
They are saying oh yeah we are using composition because we have the ability to build up an object by composing it from multiple different sources of methods. So yeah the word composition in the absolute sense of the English language, sure I can buy that, but the issue is, when quoting the book that says
favor composition over class inheritance
Those are two different types of compositions that are being addressed here.
The authors of Design Patterns are saying one object has a reference to this other object or other objects. All the blogposts are saying, let's build up the definition of an object by using different sets of methods.
To ensure we are clear what these blog posts are saying,
I will write out a really quick example to emulate how I would build up the definition of a Window.
I will follow the same pattern I just saw in that blogpost.
So I will write out a function called rectangular and the goal of this function is to take in some state object like so:
const rectangular = (state) => {}
And remember it has some instance variables tied to it and then I am going to return an object that has some methods that I am going to eventually use in some definition of something that is rectangular like so:
const rectangular = (state) => {
return {
};
};
If something is rectangular then chances are I want it to have an area()
method like so:
const rectangular = (state) => {
return {
area: () => {}
};
};
So I gave it an area method and inside of here I will return state.height * state.width
like so:
const rectangular = (state) => {
return {
area: () => {
state.height * state.width;
}
};
};
So I am very clearly making the implication that state
object that is coming in, must have a height
and a width
property. After that I will define maybe some openable
function like so:
const rectangular = (state) => {
return {
area: () => {
state.height * state.width;
}
};
};
const openable = (state) => {};
And the goal of this is to give a door presumably, the ability to toggle itself open or closed and I will do that by returning an object that has methods to implement that behavior like a method called toggleOpen like so:
const rectangular = (state) => {
return {
area: () => {
state.height * state.width;
}
};
};
const openable = (state) => {
return {
toggleOpen: () => {}
};
};
And inside of here I will say state.open
is the opposite of state.open
, so that is definitely some toggling behavior like so:
const rectangular = (state) => {
return {
area: () => {
state.height * state.width;
}
};
};
const openable = (state) => {
return {
toggleOpen: () => {
state.open = !state.open;
}
};
};
Now here is the important part, to combine or compose them into an object, I would write a single function called buildRectangleWindow
that will be called with some state object like so:
const rectangular = (state) => {
return {
area: () => {
state.height * state.width;
}
};
};
const openable = (state) => {
return {
toggleOpen: () => {
state.open = !state.open;
}
};
};
const buildRectangleWindow = (state) => {};
Now this example is slightly different than the code I got from the blogpost. In the blogpost they define that state
object directly inside the function that was intended to actually build an instance of an object, I am going to pass in those instance properties as an argument because that is way more flexible than what the example had.
So then inside of buildRectangleWindow
I will say return Object.assign(state, rectangular(state), openable(state));` like so:
const rectangular = (state) => {
return {
area: () => {
state.height * state.width;
}
};
};
const openable = (state) => {
return {
toggleOpen: () => {
state.open = !state.open;
}
};
};
const buildRectangleWindow = (state) => {
return Object.assign(state, rectangular(state), openable(state));
};
I am basically saying take the state
object, throw it into openable
, when I call openable
, it's going to return an object that has some methods on it. Then take the state
object and throw it into rectangular
and same idea. So essentially this openable
is going to return an object that has some method on it, rectangular
is going to return an object that has some method on it and then I will take all those different methods and copy paste them down to the state
object.
Now, to actually create an rectangular
window I would do the following:
const rectangular = (state) => {
return {
area: () => {
state.height * state.width;
}
};
};
const openable = (state) => {
return {
toggleOpen: () => {
state.open = !state.open;
}
};
};
const buildRectangleWindow = (state) => {
return Object.assign(state, rectangular(state), openable(state));
};
const rectangleWindow = buildRectangleWindow({
height: 20,
width: 20,
open: false
});
Now to actually use this object, I can do this like:
rectangleWindow.open
To see whether or not the window is open or not and I get false
as the output.
I can also do:
rectangleWindow.toggleOpen();
That should toggle the open status and I can print out rectangleWindow again like so:
rectangleWindow.open
And now I get true
.
So the entire idea behind this approach is that we have these separate definitions of methods and I am going to combine them together to actually build a usable object.
So when all these blogposts are using the term composition, I can buy into that this is some form of composition in the strictest sense of the literal English definition of composition, because we are composing the behaviors of an object by combining them together, but the point is that this is not the same definition of composition as you find in the Design Pattern book and that book is what everyone is quoting.
Erich Gamma and the other authors are extremely smart people who said you should use this pattern right here over class inheritance and then the blogpost authors are saying when they said composition, they meant this thing and that is just not what the authors of Design Patterns are talking about.
Erich Gamma and his co-authors were not saying to do, what I just illustrated in the code above.
This is just not a good pattern and I can show you why this is not a good pattern very easily.
Let’s say for some reason openable
also has an area
method like so:
const rectangular = (state) => {
return {
area: () => {
state.height * state.width;
}
};
};
const openable = (state) => {
return {
toggleOpen: () => {
state.open = !state.open;
},
area: () => {};
};
};
const buildRectangleWindow = (state) => {
return Object.assign(state, rectangular(state), openable(state));
};
const rectangleWindow = buildRectangleWindow({
height: 20,
width: 20,
open: false
});
rectangleWindow.open
rectangleWindow.toggleOpen();
rectangleWindow.open
So, what does that mean? It means that when I have some object that combines the methods from rectangular
and openable
, which area
method are we going to actually get?
The area
method we end up getting comes down to the order in which we list them out in the Object.assign()
statement.
So this entire pattern here is incredibly fragile. If you ever happen to have any methods with the same name. If you ever do, that’s pretty much it, you cannot combine those different sets of methods together because you are going to get super unexpected behavior.
So the same author of the code, called all this concatenative inheritance. What it really is, is multiple inheritance like so:

Thats what we are really doing here. We are building up the definition of some rectangleWindow
by combining all the different methods that are openable
and rectangular
. So you can kind of imagine that yep, I am going to copy paste, literally, in this case, all those methods from openable
and rectangular
down to rectangleWindow
.
Again that looks an awful lot like inheritance.
So it is not composition, but multiple inheritance. They are inheriting methods from multiple different sources.
I hope I have provided a better idea on what Erich Gamma and his co-authors were talking about when they were discussing object composition.