ES6 Intro
ES6 Intro
This is a quick intro to get up-to-speed with the new class syntax introduced in ES6. We’ll also cover ES modules as they’re kind of unavoidable in frontend now.
Classes
Syntax
The ES6 class syntax is an easier way to create object-oriented structures in JavaScript. Previously you had to rely on prototypical inheritance with constructor functions.
(If you’re curious about inheritance and prototypes you could check out MDN’s guide, but it’s not strictly necessary to continue)
Here’s an example:
1 | function Animal(species) { |
Any new instance of Animal
has access to whatever we put on its prototype.
This is kind of verbose and awkward (having to refer to the prototype all the time), so classes provide a new syntax for achieving the same result:
1 | class Animal { |
The outcome here is the same. getSpecies
is still on Animal
‘s prototype, but we used a nicer syntax to get there.
Constructor
The constructor
method is the equivalent of the defining function in the first example. It takes whatever arguments you call the class with when you instantiate it with the new
keyword.
Inheritance
Classes make it easy to inherit functionality from other classes. We can use the extends
keyword to access properties on the base class:
1 | class Dog extends Animal { |
super
refers to the base class you’re extending. So super('dog')
is like calling new Animal('dog')
, only from within our new class.
Modules
ES Modules are similar to Node’s require
syntax, but are a standardised part of the JS language. They let you split your code up and share it across multiple smaller files, as well as easily import external dependencies.
Node 10 has experimental support for ES Modules (but you have to pass the --experimental-modules
flag and use the .mjs
file extension). The newest browsers now have initial support, but generally we need to use a tool called a bundler to parse all our imports and “bundle” them into a single file that all browsers will understand.
We’ll cover this in more detail later—for now this project is set up so the imports should work fine.
Exports
Files can have two types of exports: default and named. Generally you use default exports if there’s only one thing in a file that needs to be accessible outside of it. You’d use named exports to export multiple things (e.g. from a collection of utility functions). This is similar to how you might do module.exports = a
for a single Node export, or module.exports = { a, b }
to export an object with multiple properties.
This is how you default export something:
1 | const a = 1; |
And this is how you named export something:
1 | const a = 1; |
You can only default export a single thing, but you can have as many named exports as you like:
1 | const a = 1; |
You’ll also see this briefer version of named exports:
1 | export const a = 1; |
Imports
There are also two kinds of imports: default and named. This is how you import something that was default-exported:
1 | import a from './a'; |
This is how you import named-exports:
1 | import { a } from './a'; |
You can import as many named-exports as you like on the same line:
1 | import { a, b } from './a'; |
Important: when you import a default-export you can call it whatever you want. You’re effectively creating a new variable and assigning the default-export to it. In contrast named-exports have to imported with the correct name—otherwise JS would have no idea which export you wanted.
Also important: unlike Node’s require
ES Modules are not dynamic. This means you cannot put them inside your code and import things conditionally. You also cannot use a variable in an import path. E.g.
1 | const myVar = 'a'; |
Exercise
- Clone the project and run
npm i
npm t
to run the test watcher- Rewrite
Character
andHero
to use ES6 classes and ES Modules - You may need to change
index.js
too - Keep all the tests passing!