- Attach attributes to a new object using the constructor function
- Recall the cost of defining methods inside a constructor function
- Fork and clone this repository.
- Change to the new directory.
- Install dependencies.
- Create and checkout a new branch,
training
Now that we're using objects to solve problems, it might make sense to have a way to make multiple objects with the same kind of format - an 'object factory', designed to construct objects of a particular type.
Suppose we had the following object describing a favorite comic book hero:
const batman = {
name: 'Bruce Wayne',
alias: 'The Bat-man',
usePower: function() {
return 'Spend money and hit people';
},
};
And now we want another object describing a different hero:
const wonderWoman = {
name: 'Diana Prince',
alias: 'Wonder Woman',
usePower: function() {
return 'Deflect bullets with bracelets';
},
};
Why is this not a good answer?
Because copy-and-paste reuse is one of the biggest sources of errors in software development.
What features do batman
and wonderWoman
share? Remember to think about
attributes and methods when you're modeling. Also take note of what differs
between them.
Make a diagram of our Hero
entity based on the above objects.
JavaScript's answer to the copy-and-paste reuse problem is constructor functions. Constructor functions:
- Always start with a capital letter (convention)
- Are always used with the
new
keyword (self-enforced)
Bad things happen when you break these rules.
Let's make a Hero constructor function. We'll make use of the function to reduce duplication in our objects, while allowing the difference to vary by only defining the differences when we construct the new object.
const usePower = function () {
return this._power;
};
const Hero = function (name, alias, power) {
this.name = name;
this.alias = alias;
this._power = power;
this.usePower = usePower;
};
It is conventional to use a leading underscore (_
) on a property name to
indicate to future developers that the property is not intended for direct
access or assignment. Nothing in JavaScript enforces this convention, but
developers should consider any property with a leading underscore private to
object (not accessible from the outside).
const
is just like let
, except const
will not let you re-assign a value
to the same name.
const foo = 'bar';
foo = 'baz'; // explode!
What does my choice of const
tell you about my expectations for constructor
functions?
We defined a method inside the the Hero
constructor, but doing that is a Bad
IdeaTM. JavaScript allows it, but don't do it.
We'll see the right way to achieve a near identical and preferred result
shortly.
Now, let's create wonderWoman
using the constructor function instead of an
object literal:
const wonderWoman = new Hero('Diana Prince',
'Wonder Woman',
'Deflect bullets with bracelets');
//=> undefined
wonderWoman;
/* => { name: 'Diana Prince',
alias: 'Wonder Woman',
power: 'Deflects bullets with bracelets',
usePower: [Function] }
*/
new
, a JavaScript keyword, does the following, in order:
- creates an empty object (
{}
) - attaches the constructor function to the object as a property
- invokes the constructor function as a method on the object
- returns the object
A new object created this way is sometimes called an 'instance' of type Hero
.
Refactor the run tracker code from the previous lesson to use constructor functions instead of copying properties between object literals.
Leave the methods out for now. We'll add them back shortly.
There are no tests for this (yet), but you can still use grunt nag
to lint
your code and look for syntax errors.
You should have at least two constructor functions when you've finished.
- All content is licensed under a CCBYNCSA 4.0 license.
- All software code is licensed under GNU GPLv3. For commercial use or alternative licensing, please contact legal@ga.co.