No description, website, or topics provided.
Switch branches/tags
Nothing to show
Clone or download
tvlangley
Latest commit e6fbbb3 Apr 17, 2019

README.md

General Assembly Logo

JavaScript Constructors and Prototypes

Prerequisites

Objectives

  • Use a constructor function to produce objects of a particular type.
  • Attach attributes to a new object using the constructor.
  • Recall the cost of defining methods inside a constructor function.
  • Define methods on custom objects by attaching them to the prototype.

Preparation

  1. Fork and clone this repository.
  2. Change to the new directory.
  3. Install dependencies.
  4. Create and checkout a new branch, training

Constructors

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.

Lab: Model a Hero

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.

Demo: Constructors

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 the 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 Hero constructor, but doing that is a bad idea. 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:

  1. Creates an empty object ({}).
  2. Attaches the constructor function to the object as a property.
  3. Invokes the constructor function as a method on the object.
  4. Returns the object.

A new object created this way is sometimes called an 'instance' of type Hero.

Lab: Refactor Object Literals Using Constructors

Refactor the run tracker code from the previous lesson to use constructor functions instead of copying properties between object literals. Do your work in the lib/runs.js file.

There are tests for the lab which can be run with grunt test.

You should take the user object and move some of the code into the User constructor function, and some of the code into the Run constructor function. You should remove or comment out the console.log statement when you are ready to run the tests.

Prototypes

In the previous section, we saw how to use constructors to deduplicate effort in creating new objects that share attributes. We learned that we should never define a method inside a constructor function, because we will end up with a copy of that function inside every instance. So how should we get behavior in our custom objects?

Code Along: Add Methods to the Prototype

  1. Create usePower and attach it to the constructor function's prototype.
  2. Create a method to say the hero's name and alias. Attach it to the prototype.
  3. Create batman and wonderWoman. Call the method just attached.
  4. Observe that this method isn't part of objects created using the constructor function.

Lab: Add Methods to the Prototype

Change the run tracker code you made in the previous lab to use prototypes.

There are tests for the lab which can be run with grunt test.

Additional Resources

License

  1. All content is licensed under a CC­BY­NC­SA 4.0 license.
  2. All software code is licensed under GNU GPLv3. For commercial use or alternative licensing, please contact legal@ga.co.