Reputation: 121
As this example is copy/pasted from inline tags in my html file, the formatting may be off.
Anyhow, I'm new to JS and have a syntax question. This example is from an MDN basics of JS article. Here is a simple shape class:
class Shape {
constructor(name, sides, sideLength) {
this.name = name;
this.sides = sides;
this.sideLength = sideLength;
}
calcPerimeter() {
console.log(this.sides * this.sideLength);
}
}
Then, I want to extend it with a Square class
class Square extends Shape {
constructor(name, sides, sideLength) {
super(name, sides, sideLength);
}
calcArea() {
console.log(this.sideLength * this.sideLength);
}
}
Now, this is obviously a bit silly. It's a Square class, so the name should always be "square", and it should always have 4 sides. We can remove the name and sides parameters.
class Square extends Shape {
constructor(sideLength) {
super(sideLength);
this.name = "square;
this.sides = 4;
}
calcArea() {
console.log(this.sideLength * this.sideLength);
}
}
The problem is this doesn't work, and I'm not sure why. I would think I could now do let square = new Square(5); but sideLength is undefined. If I explicitly set this.sideLength to sideLength in Square class, it fixes the problem, but then I'm not inheriting anything from Shape class. What's wrong with my syntax here? How do I do what I'm trying to do (inherit sideLengths from Shape)?
Upvotes: 1
Views: 63
Reputation: 16908
To follow the inheritance hierarchy, you need to call the super constructor with the values from the child constructor. You do not need to assign new properties to this
instead you can pass the properties for the Square
using the super(...)
call:
class Shape {
constructor(name, sides, sideLength) {
this.name = name;
this.sides = sides;
this.sideLength = sideLength;
}
calcPerimeter() {
console.log(this.sides * this.sideLength);
}
}
class Square extends Shape {
constructor(sideLength) {
super("square", 4, sideLength);
}
calcArea() {
console.log(this.sideLength * this.sideLength);
}
}
const square = new Square(5);
square.calcArea();
When you do not pass the properties name
and sides
to the parent constructor and only pass sidelength
, the name
gets initialized with the value of sidelength
due to the position of the parameter in the parent constructor:
constructor(sideLength) {
super(sideLength);
this.name = "square";
this.sides = 4;
}
Makes the call to the parent constructor like so:
Shape(sidelength, undefined, undefined)
So as the last parameter which is sidelength
becomes undefined
, when you try to call the calcArea
it does not work.
Upvotes: 2
Reputation: 370689
When you do
super(sideLength);
This calls the parent constructor with one argument, the sideLength
. So, this runs:
constructor(name, sides, sideLength) {
this.name = name;
this.sides = sides;
this.sideLength = sideLength;
}
which turns into, since only the first argument, name
, has a value in it:
this.name = sideLengthPassedFromSquare;
this.sides = undefined;
this.sideLength = undefined;
IF you want to be able to omit properties passed like this, have the super constructor either list the required properties first (like sideLength
):
constructor(sideLength, name, sides) {
Or pass a single object instead:
constructor({ name, sides, sideLength }) {
and do
super({ sideLength })
Upvotes: 1