- [Instructor] Building objects with object literal notation
makes for easy to read code.
However, it isn't ideal for every situation.
If you're making multiple copies of similar objects,
you're going to have to write redundant code
and you also can't easily abstract out
what you're doing for reuse.
For just these scenarios,
JavaScript includes another way to create objects
by creating a constructor function.
JavaScript include some built in constructor functions
which you can use to create things as the name implies.
These start with capital letters
and they're most commonly used with data types.
So for instance, the code new array creates a new array,
and likewise, new object creates a new object,
and I can pass some arguments there if I want to.
Now a really great thing about constructor functions
is that we can make our own,
so we can define the object
that we want the function to create,
and then all we have to do is call the constructor function,
pass in the arguments, and we have a new custom object.
So for instance, in our Hansel and Petal code,
we're creating objects for different types of items
that users buy.
So we can create a constructor function
that creates an object
with the specific properties and methods
for each item type that users can buy,
and then we can call those constructor functions
to build out objects in response to user actions.
And that should dry out our code some
and keep it a little better organized.
So looking in the product add method
in the if else construction
where we actually build out the objects
starting here on line 459,
we have four different types of objects,
we have arrangements, we have live plants, we have bouquets.
And then for each bouquet,
we add a sub object for each type of stem
that users add to the bouquet.
So we could use four different constructor functions here
for arrangements, live plants, bouquets,
and then for individual flowers.
So I'll go to the very end of the file
to build out my constructor functions
just before the closing line of the iffy.
And to build a constructor function,
I simply declare a new function,
so I'll call it the first one Arrangement.
And I'll name it with a capital A
to indicate that it's a constructor.
Now note that this isn't a syntactic thing,
it would still work as a constructor function
even if the name were all lowercase.
But it's a best practice to name constructors
with an initial cap
as a convention to make it clear what they do.
And our constructor is going to take a few parameters,
first name, and then vase for the vase type,
and then quantity.
And we'll use a default parameter,
so setting a value to one if it's not otherwise specified.
Now when we call this constructor function,
it's going to create a new empty object for us.
And we can look at our existing code
to see what properties and methods we need.
So first, there's the type key with a value of floral,
and so within the function,
we can use the this key word with keys and values
to add any key value pair that we want
to the new object that's being created.
So this.type equals floral
and likewise for the other properties.
So this.storage equals cool,
this.name,
and we're going to use the name parameter here,
this. vase will likely use the vase parameter value.
This.quantity equals the value of the quantity parameter.
And then we want that log item method,
so I'm going to scroll up to my existing code
and I'm just going to copy that.
I have it written and it's working,
and then I will scroll down and say this.logItem,
and then I have to convert that object code to a statement.
And then I just need to repeat this
for a live constructor function.
And enough of it is similar that I'm just going to copy
and paste the arrangement constructor.
So copying that constructor
and then a new line just pasting it in,
and I'll change that name arrangement
to live with a capital L.
And that second parameter instead of a vase
for live arrangement, we have a pot,
so we'll change that parameter name.
And so the storage value needs to be warm,
so we'll change that.
And from this.vase,
we need to instead specify this.pot key,
and we will again, use that pot parameter value.
And otherwise, everything's the same,
so now we have two constructor functions built out.
And we'll do a similar process for bouquet.
And so I'm going to copy that arrangement function again,
paste that in,
we'll change the name to bouquet with a capital B.
And we don't have an option currently in our view
for users to actually choose more than one for the quantity,
so we'll just take that quantity parameter out altogether
and remove quantity as a key.
And then we're going to create a final constructor
for flowers.
And so we'll write that from scratch,
it'd be a function called flower with a capital F,
and it's going to accept two parameters,
quantity, and then color.
Now here we want the key to be the color of the stem
and the value to be the quantity of that stem color.
So we're going to say this [Color] equals quantity,
and then we're going to grab that log item function
from another constructor,
and we'll copy that over.
And we'll do one final piece of customization.
Back up in the bouquet function,
it would be useful bouquet objects
to have an add stem function
that can create sub objects using the flower constructor.
So we'll start by creating a sub object using this.flowers,
and this is where the data for each stem is grouped.
And then we'll add, addStem as a function
to that sub object,
and that's going to take a few parameters.
So name, quantity,
and we'll set a default parameter of one,
and color, and we'll set a default parameter there as well
to default.
And we'll capitalize that
because the rest of our stem colors
are going to be initial caps as well.
And then this function is going to set a key
which will be this [Name],
with a value equal to the result
of calling the flower constructor,
and to do that, we'll say new capital Flower,
and passing in the quantity and color parameters
that the flower constructor expects.
And so we're leveraging our flower constructor
in a method for bouquet objects.
And so now to make use of our constructors,
we'll scroll back up,
and on line 459 is the beginning of our if else logic
for item type.
So in the arrangement section,
first off, I can comment out all of the code here
that uses an object literal
to assign a value to new item for an arrangement,
so that's lines 460 to 472,
and I'll comment that all out,
and I can replace that all with a single statement
using my constructor function.
And so I'm still assigning the value of new item
and its value is going to be the result
of running that arrangement constructor,
and so we just use the new keyword,
call our arrangement function,
and so for the name,
we are going to be using data object.itemname,
just like we were,
and for the vase type,
we're using dataObject.vasetype.
And then for the quantity, we can pass dataObject.qty.
And that's it,
we've replaced all of that code
with just a single statement leveraging our constructor.
And so very similar for the live section,
so starting out, I'm going to comment out lines 475 to 487,
that object literal,
and then we'll set the value of new item
to the result of calling the live constructor
using the new keyword,
and we're going to pass in dataObject.itemname
for the name, dataObject.pottype for the pot,
and dataObject.qty for the quantity.
And then for bouquets,
scrolling down past that nested if else,
we're going to come and outlines 495 through 507,
and then we're going to assign new item
the result of calling new Bouquet
and passing dataObject.itemname,
and dataObject.vasetype.
And then finally moving down a little more,
we have code that creates sub object for stems,
and we can use our flower constructor here.
So in the if statement, commenting out these lines,
520 through 522 that create and customize
newItem.flowers key,
we can instead use the add stem method
that we created for the bouquet object,
which leverages the flower constructor.
And so newItem.flowers.addStem,
and then we pass it the key that we've derived,
dataObject[Item] for quantity, dataObject
square bracket,
and the text color plus the stem type
that we've derived above for the color.
And then in the else statement,
commenting out these four lines, 526 through 529,
and instead, calling newItem.flowers.addStem,
passing key and dataObject[Item].
And then saving our changes,
and starting up the server for the current folder,
and then going to local host 8080,
opening up the console,
and then saving our changes
and opening the arrangements page
from the HTTP server with the console open,
we'll add this to the cart.
And I see that the object is logged
and it's the same as it was previously using
the object literal, it has the name and vase, the quantity,
the log item method, all of my key value pairs.
Now my cart's getting a little full,
which is logged down here,
and I'd like to be able to verify what I'm creating now
and not see what I created in earlier testing.
So I can call the jQuery removed cookie method
to clear out the basket data cookie.
So that's $.removeCookie
and passing it the string basket data.
And I'm going to do the same thing for the bouquet count
and for the qty cookie.
And so now when I do $.cookie,
there's a couple other cookies in there
that I'm not so worried about,
but this will keep that whole basket data reined in.
And so I'll go ahead and add this arrangement
to the basket again,
now I've got just one item in the basket.
And then moving to the live plants page,
I'll add that to the basket too.
And again, I get another object just like it was before
with the literal.
And then finally, I'll go to the builder bouquet page,
I will take a couple of a flower that takes a color,
I will take a few of a flower that doesn't take a color,
add that to the cart,
and again, the object is logged.
And drilling into that flowers property,
we have not only our two objects
that were created using that flower constructor,
but also we have that add stem method
that we added to the flowers object.
And we've done this using constructor functions
instead of object literals.
And so we've abstracted our code,
so the logic is one place, the constructors,
and our procedural code for adding items to the basket
is cleaner by just using single statements
to call those constructors,
so we've separated our concerns a bit here,
and that's a win.