Dave
Dave

Reputation: 2018

Using method from super class returns undefined after result

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

Answers (4)

Dave Meehan
Dave Meehan

Reputation: 3201

What does Console.log do?

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.

Functions vs arrow functions

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'

Use of 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.

Revised Code

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

RenaudC5
RenaudC5

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

Ryan Zhang
Ryan Zhang

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

gfringeli
gfringeli

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

Related Questions