9

I am curious as I get a "undefined is not a function" error. Consider the following class:

var FlareError = require('../flare_error.js');

class Currency {

  constructor() {
    this._currencyStore = [];
  }

  static store(currency) {
    for (var key in currency) {
      if (currency.hasOwnProperty(key) && currency[key] !== "") {

        if (Object.keys(JSON.parse(currency[key])).length > 0) {
          var currencyObject = JSON.parse(currency[key]);
          this.currencyValidator(currencyObject);

          currencyObject["current_amount"] = 0;

          this._currencyStore.push(currencyObject);
        }
      }
    }
  }

   currencyValidator(currencyJson) {
    if (!currencyJson.hasOwnProperty('name')) {
      FlareError.error('Currency must have a name attribute in the json.');
    }

    if (!currencyJson.hasOwnProperty('description')) {
      FlareError.error('Currency must have a description attribute in the json.');
    }

    if (!currencyJson.hasOwnProperty('icon')) {
      FlareError.error('Currency must have a icon attribute in the json.');
    }
  }

  static getCurrencyStore() {
    return this._currencyStore;
  }

};

module.exports = Currency;

Refactoring aside, the issue is on the line: this.currencyValidator(currencyObject); I get the error "undefined is not a function"

I assume this is because I have a static method who's internals call a non static method? Would that non static method have to be static? and if so does the concept of this.methodName still work?

TheWebs
  • 12,470
  • 30
  • 107
  • 211
  • 2
    I wonder why you decided to make `store` static because it seems that you don't know what `static` means. – a better oliver Oct 27 '15 at 15:46
  • Of course a static method can call a non-static one *when it has an instance to invoke it on*. Where's your instance? – Bergi Oct 27 '15 at 17:20

3 Answers3

15

No, a static method cannot call a non-static method.

Consider that you have objects a and b, both instances of Currency. currencyValidator exists on those two objects. Now store() belongs to the class Currency itself, not one of those objects. So, in Currency.store(), how does it know which object to call currencyValidator() on? The simple answer is it doesn't so it can't. This is one of the pitfalls of using static methods and one of the reasons people often urge against them.

Regardless, you can get around this by passing a into Currency.store(), and calling a.currencyValidator() instead.

Josh
  • 8,079
  • 3
  • 24
  • 49
6

It makes no sense to call a non-static function from a static one, in any language. Static (in this context) means that it's basically outside of the object, independent in all but name. It's not tied to any instance and thus there's no this or self to call non-static (ie member) fields.

Blindy
  • 65,249
  • 10
  • 91
  • 131
  • 1
    …except when the static method gets one (or more) instance(s) as an argument; or when it constructs an instance by itself. Of course, `this` does refer to the class itself. – Bergi Oct 27 '15 at 17:22
  • I don't see how that's an "except", it still has no `this`. – Blindy Oct 27 '15 at 17:52
  • The "…except" was meant to finish the first sentence about "making sense". You cannot call instance methods from a static one using `this` indeed, but you might not need `this`. – Bergi Oct 27 '15 at 17:54
1

No, in general static methods cannot call instance methods. It makes little sense to be able to do so.

The only caveat is that there is nothing stopping a static method instantiating an instance of a class, at which point it can call the instance methods in the usual way.

Jamiec
  • 133,658
  • 13
  • 134
  • 193