- [Sasha] Using a prototype can reduce the memory footprint
of an app, when you're creating a number of object
using a constructor function.
But you may still experience some duplication in your code.
If you have multiple constructor functions
that share properties, and/or methods.
To further optimize your code,
JavaScript allows you to base one prototype on another.
Inheriting keys and values, for another prototype,
rather than creating and storing unique copies
for each separate prototype.
Building relationships between prototypes
in this way is known as chaining or inheritance.
The resulting set of relationships
between different prototypes, is known as a prototype chain.
In the Hansel and petal code for instance,
we're working with four separate constructors,
each with its own prototype.
For arrangements, live plants, bouquets, and flower stems.
Each of these prototypes includes the type property
with a value of floral.
And each of these prototypes also includes
a log item method, with identical code.
So right off the back, we could eliminate the duplication
among all of these constructors, by basing them
on the same prototype.
But if we look closer, we also find
that some of our prototypes share properties
and values, that are not shared with all prototypes.
In fact, we can build out a set of chained prototypes
in which some are based on others,
without all of them sharing the same properties.
Before we dig in, it can be useful to sketch out
the structure and relationships between our constructors.
To determine just what our prototype change
should look like.
All of our constructors share a type of property,
and the log item method.
So we can create a generic item prototype that serves
as the origin of our prototype chain.
And then our existing constructors fall
into three distinct categories based on their shared values.
Flower is unique, as is live.
But arrangement and bouquet both have the pot,
and storage properties and values in common.
So we can create a parent constructor for cut items,
and then chain the arrangement,
and bouquet constructors to that.
So let's code this up.
Before the arrangement constructor,
I'm gonna create a new constructor called item,
and that's just gonna be an empty function.
We don't want it to actually customize anything.
We just wanna actually work with its prototype.
And so I'm gonna go down here to arrangement,
and copy the prototype statement for the type property,
paste that up here, and change arrangement to item.
So we are customizing the prototype of the item constructor,
with the type value of floral,
and I'm gonna do the same thing with the log item method.
Changing arrangement to item.
So now we have a generic item constructor,
whose prototype includes values for the type, property,
and the log item method.
And so now if we chain all the rest of our constructors
to item, we don't have to duplicate
either of those key value pairs,
in any of our other constructors.
So then we have identified these three categories,
and because arrangement and bouquet,
both share some common properties,
I'm gonna cut and paste arrangement, and move it down
to the bottom, right before the end of our file.
And so I'm gonna do the same thing with bouquet,
and move that down here after arrangement.
And so now we have the live constructor,
and the flower constructor, right after the item constructor
and it's prototype information.
And so for the live constructor, first off
we're not gonna make any changes to the constructor itself,
but down here in our prototype statements,
we are specifying the type value,
and we're specifying the log item value.
And instead of doing those,
we can just inherit those from the item constructor.
And to do that, I'm gonna create a new statement,
live.prototype equals new item.
And so this specifies item,
as the parent in the prototype chain.
Meaning that live is going to inherit its prototype,
from the item constructor.
And because that item prototype already has floral
and log item,
we don't need to specify those again for the live prototype.
So I can delete the type statement for live,
as well as the log item statement.
And so we've dried out our code here
by ensuring that the type property and the log item method,
occurred just once in our code base.
And so we can do the same thing
with the flour constructor here.
So again, we're gonna leave the constructor as it is,
but down here we are specifying the log item function again
for the flower prototype.
And instead of doing that,
I can simply specify flower.prototype equals new item.
And then flower's going to inherit that log item function.
It's also going to inherit the type property,
which I neglected to include,
but it should be included as a property of flower.
So that also is ensuring that properties
that we intend to apply to all of the objects,
actually are rolled out to all of the objects.
So that actually in this case creating a prototype chain
helped us identify a hole in our code.
So I can take out the log item method from flower,
because now that we have specified item
as the parent and the prototype chain,
we will automatically be inheriting blog item method
as well as the type property from item.
Okay, so live and flower were the two constructors,
that were unique in our prototype chain.
And now we come to an arrangement in bouquet.
And so arrangement and bouquet do also share
the type property value of floral and the log item method.
But between the two of them
they also share a storage value of cool.
And so to dry out our code a little bit further,
we can create another intermediate link
in the prototype chain, that arrangement and bouquet
will both descend from.
So before arrangement,
I'm gonna create a function called cut,
and it's gonna be blank.
And so this is just gonna be a constructor function.
And so cut is the category that arrangement and bouquet
both belong to, they're both types of cut flowers.
And what's common to cut flowers,
are things that we can actually specify
as part of the prototype.
So cut.prototype.storage equals cool.
And then what we also wanna do,
is specify that cut descends from item.
And so we'll say cut.prototype equals new item.
And so cut is a slightly customized object
based on the item prototype.
And now that we have this object
with a storage value of cool,
we can specify that as the parent in the prototype chain
for both arrangement and bouquet.
So for arrangement, I'm gonna say,
arrangement.prototype equals new cut.
So specifying cut as the parent in the prototype chain.
And now we can take out type because cut descends from item.
So we're getting that type, and I can take out log item,
because cut descends from type and we're getting log item.
And then I can also take out storage,
and so arrangement now inherits
all of its non-customized properties from cut,
an item which are further up the prototype chain.
And likewise for bouquet,
we're gonna specify bouquets prototype,
as a new instance of cut.
And then we are inheriting type from the parent of cut,
which is item.
We are inheriting log item, also from item.
And we are inheriting storage from cut,
and then specific to bouquet is this flowers property,
and that's going to stay as a customization
for bouquet itself.
And so we can save our work.
And I have my files being served from HTTP server.
I have reloaded, and so going to arrangements,
we can test this all out.
I'm gonna add an arrangement to the basket.
And again, I'm getting the custom properties
name, base, quantity, and storage,
and I'm getting the inherited type and log item.
And over in live plants, I'll add one of those.
And the same thing, this works just like it did before,
where we have our custom properties,
and our inherited properties.
And then over and build a bouquet,
we'll take six yellow Calla lilies, and an Iris.
And we have our custom properties, including flowers.
We have inherited storage from the cut prototype,
and we've inherited type and log item
from the item prototype.
And so again, we see that our code works
just like it did before,
but we have further optimized our code
and reduce duplication.
(upbeat music)