Reputation: 2018
I am playing around with classes and I noticed that after checking status I am seeing the console log, but afterward I am seeing undefined
. Can anyone explain how to get around this and why is this happening?
class Test {
constructor(name) {
this.name = name;
}
status() {
console.log("test")
}
}
class Test1 extends Test {
constructor(name) {
super(name);
}
checkStatus() {
super.status();
}
}
const b = new Test1("Test")
console.log(b.checkStatus())
Upvotes: 0
Views: 523
Reputation: 3201
The method console.log
does not return a value. This seems to be a common misunderstanding, people seem to assume that it will return what is printed to the log.
However, even if that was an assumption, status()
does not have an explicit return, so the value is undefined
.
Here another misunderstanding creeps in, which is the difference between regular functions and arrow functions. Arrow functions have a convenience which is that if the function body resolves to a value, its taken as the return value. Consider:
function foo() {
return 'foo'
}
console.log(foo()) // foo() returns 'foo', so the log shows 'foo'
const bar = () => 'bar'
console.log(bar()) // bar() returns 'bar', so the log shows 'bar'
const baz = () => console.log('baz')
console.log(baz()) // baz() returns undefined, so the log shows 'baz' and 'undefined'
super
checkStatus() {
super.status();
}
You use super
here for no (good) reason. status()
has been inherited from class Test
, and can be called with this.status()
. You would only need to use super.status()
if you were providing an override in Test1
and needing to call the parent class implementation.
I suspect that this is actually what you intended, but because of the lack of return
statements, you were trying to understand what was being called where and got sidetracked.
Here I've renamed the classes to make things a little clearer.
TestBase
provides our base class functionality.
TestOverride
provides an override implementation of status
that prepends its own name to the value returned by TestBase.status
, called via super
(this.super()
here would create an infinite loop).
TestNoOverride
does not add anything to TestBase
, so the return value is just as per TestBase
(but note that it is using the name passed into the constructor.
The most important lesson here is that YOU MUST provide an explicit return value if you expect to be able to assign (or log) the return value from a function. The exception to this is if the function is an arrow function with a simple statement as the function body, in which case the arrow function takes that value as the (implicit) return.
class TestBase {
constructor(name) {
this.name = name;
}
status() {
return "TestBase " + this.name
}
}
class TestOverride extends TestBase {
constructor(name) {
super(name);
}
status() {
return "TestOverride " + super.status();
}
}
class TestNoOverride extends TestBase {
constructor(name) {
super(name);
}
}
const a = new TestBase("A")
console.log(a.status())
const b = new TestOverride("B")
console.log(b.status())
const c = new TestNoOverride("C")
console.log(c.status())
Upvotes: 1
Reputation: 3829
This happens because your checkStatus
method does not return anything.
It's the same as if you were doing
function hello(){
console.log('hello')
}
console.log(hello())
If you want your function to return something you can return something in the parent method and in the checkStatus
method
class Test {
constructor(name) {
this.name = name;
}
status() {
return "test"
}
}
class Test1 extends Test {
constructor(name) {
super(name);
}
checkStatus() {
return super.status();
}
}
const b = new Test1("Test")
console.log(b.checkStatus())
Upvotes: 0
Reputation: 1920
Consider this line:
console.log(b.checkStatus())
This runs checkStatus()
in the Test1
class, which runs status()
in Test. Well, consider status()
:
console.log("test")
Ok, "test" is printed to the console. Now, as there is no return function, undefined
is implicitly returned. checkStatus()
therefore returns this value, undefined
. You then log this with console.log(b.checkStatus())
, printing undefined
.
If you look carefully, you have two console.log()
s in your program. Hence the two outputs, the second being undefined
.
Upvotes: 0
Reputation: 26
You are logging the value returned by b.checkStatus()
, which is undefined
as the function does not return a value. Most likely you do not want this return value to be logged.
class Test {
constructor(name) {
this.name = name;
}
status() {
console.log("test")
}
}
class Test1 extends Test {
constructor(name) {
super(name);
}
checkStatus() {
super.status();
}
}
const b = new Test1("Test")
b.checkStatus()
Upvotes: 0