If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
In PHP, a class can extend another class. So, can we do that in JavaScript? Totally! And once again, you're going to love it.
To try this out, let's go back to the play.js
file. Create a new class: AGreatClass
,
because, it's going to be a great class. Give it a constructor
with a greatNumber
arg and set that on a property:
class AGreatClass { | |
constructor(greatNumber) { | |
this.greatNumber = greatNumber; | |
} | |
... lines 6 - 9 | |
} | |
... lines 11 - 16 |
Below, add one new method: returnGreatThings
, which it will, because it's going
to return our greatNumber
!
class AGreatClass { | |
... lines 3 - 6 | |
returnGreatThings() { | |
return this.greatNumber; | |
} | |
} | |
... lines 11 - 16 |
Finally, create a new constant, aGreatObject
, set to new AGreatClass(42)
. Let's
console.log(aGreatObject.returnGreatThings())
:
class AGreatClass { | |
... lines 3 - 9 | |
} | |
const aGreatObject = new AGreatClass(42); | |
console.log( | |
aGreatObject.returnGreatThings() | |
); |
There's no mystery about what this is going to return. Run the file! Yep, 42!
Now, let's create another class, class AnotherGreatClass
, because we're on a roll.
But, I want this to be a sub class of AGreatClass
. How? The same way we do it
in PHP: extends AGreatClass
:
class AGreatClass { | |
... lines 3 - 9 | |
} | |
class AnotherGreatClass extends AGreatClass{ | |
} | |
... lines 15 - 20 |
That is it. We're not overriding anything yet, but this should work. Change the variable
to be a new AnotherGreatClass
, and then run the file!
class AGreatClass { | |
... lines 3 - 9 | |
} | |
class AnotherGreatClass extends AGreatClass{ | |
} | |
const aGreatObject = new AnotherGreatClass(42); | |
... lines 17 - 20 |
Success!
From here, pretty much all the rules of extending things in PHP work in JavaScript,
with just a little bit of a different syntax. For example, we can override returnGreatThings()
.
Let's return something else that's great: adventure
!
class AGreatClass { | |
... lines 3 - 6 | |
returnGreatThings() { | |
return this.greatNumber; | |
} | |
} | |
class AnotherGreatClass extends AGreatClass{ | |
returnGreatThings() { | |
return 'adventure'; | |
} | |
} | |
const aGreatObject = new AnotherGreatClass(42); | |
... lines 19 - 22 |
This completely overrides the parent class method.
Okay, but what if we want to call the parent method. In PHP, we would say
parent::returnGreatThings()
. Well, in JavaScript, the magic word is super
:
let greatNumber = super.returnGreatThings()
. Let's return an array of great things,
like greatNumber
and adventure
:
class AGreatClass { | |
... lines 3 - 6 | |
returnGreatThings() { | |
return this.greatNumber; | |
} | |
} | |
class AnotherGreatClass extends AGreatClass{ | |
returnGreatThings() { | |
let greatNumber = super.returnGreatThings(); | |
return [greatNumber, 'adventure']; | |
} | |
} | |
const aGreatObject = new AnotherGreatClass(42); | |
... lines 21 - 24 |
This time, it prints both. Love it!
Can we override the constructor
in the same way? Because really, I should be
able to pass the greatNumber
and the great thing, adventure
, into this class.
Override the constructor
and give it just one argument: greatWord
. Then, set
this.greatWord = greatWord
:
... line 1 | |
class AGreatClass { | |
constructor(greatNumber) { | |
this.greatNumber = greatNumber; | |
} | |
... lines 6 - 9 | |
} | |
class AnotherGreatClass extends AGreatClass{ | |
constructor(greatWord) { | |
this.greatWord = greatWord; | |
} | |
... lines 16 - 21 | |
} | |
... lines 23 - 28 |
Before we try to print that below, what do you think will happen when we run this?
We're setting the greatWord
property... but we're not calling the parent constructor.
Actually, try to run it!
Ah, we get an error in the constructor
!
ReferenceError:
this
is not defined
Interesting! Inside construct()
, there is no this
variable? And PhpStorm is
trying to tell us why:
Missed superclass's constructor invocation
Unlike PHP - where calling the parent constructor is usually a good idea, but ultimately optional - in JavaScript, it's required. You must call the parent's constructor.
So let's give this two arguments: greatNumber
and greatWord
:
... lines 1 - 11 | |
class AnotherGreatClass extends AGreatClass{ | |
constructor(greatNumber, greatWord) { | |
... lines 14 - 15 | |
this.greatWord = greatWord; | |
} | |
... lines 18 - 23 | |
} | |
... lines 25 - 30 |
To call the parent constructor... it's not what you might think: super.constructor()
.
You actually treat super
like a function: super(greatNumber)
:
... lines 1 - 11 | |
class AnotherGreatClass extends AGreatClass{ | |
constructor(greatNumber, greatWord) { | |
super(greatNumber); | |
this.greatWord = greatWord; | |
} | |
... lines 18 - 23 | |
} | |
... lines 25 - 30 |
Below, let's print out this.greatWord
and pass in 42
and adventure
:
... lines 1 - 11 | |
class AnotherGreatClass extends AGreatClass{ | |
... lines 13 - 18 | |
returnGreatThings() { | |
let greatNumber = super.returnGreatThings(); | |
return [greatNumber, this.greatWord]; | |
} | |
} | |
const aGreatObject = new AnotherGreatClass(42, 'adventure'); | |
... lines 27 - 30 |
Try this out!
Yes! It works! Oh man, are you feeling like a JavaScript class pro or what? Now let's talk about something kinda weird: destructuring!
"Houston: no signs of life"
Start the conversation!
// composer.json
{
"require": {
"php": "^7.2.0",
"symfony/symfony": "3.2.*", // v3.2.14
"twig/twig": "2.10.*", // v2.10.0
"doctrine/orm": "^2.5", // v2.7.1
"doctrine/doctrine-bundle": "^1.6", // 1.10.3
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.2
"symfony/swiftmailer-bundle": "^2.3", // v2.4.2
"symfony/monolog-bundle": "^2.8", // v2.12.1
"symfony/polyfill-apcu": "^1.0", // v1.3.0
"sensio/distribution-bundle": "^5.0", // v5.0.22
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.19
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"friendsofsymfony/user-bundle": "~2.0@dev", // dev-master
"doctrine/doctrine-fixtures-bundle": "~2.3", // v2.4.1
"doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.1
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"friendsofsymfony/jsrouting-bundle": "^1.6" // 1.6.0
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.1.2
"symfony/phpunit-bridge": "^3.0" // v3.2.2
}
}