How to get a reference to a class function in ES6?

11,307

Solution 1

class MyClass {
  method(args) {}
}

is short hand for:

function MyClass() {}
MyClass.prototype.method = function(args){};

What you are looking for is a static method on the constructor, which in ES{3,5} is done this way:

function MyClass() {}
MyClass.method = function(args){};

and in ES6 is done with the static modifier:

export default class {
  static func1(a, b) { /* stuff */ }
  static func2(a, b) { /* stuff */ }
}

However, you can use short-hand methods even in an object, so using a normal object is clearer in the general case:

export default {
  func1(a, b) {/* stuff */},
  func2(a, b) {/* stuff */}
}

Why aren't prototype methods available on the constructor?

Because it's not that way in ES3 or ES5:

function MyClass() {};
MyClass.prototype.method = function(args) {};

MyClass.method  // undefined

var instance = new MyClass();
instance.method  // function(args) {}

Creating an instance is necessary to have access to methods on the prototype.

Solution 2

Why did you switch to a class construct (which is a bit more than syntactic sugar for a constructor and a prototype with the methods)? There is no reason not to use an object literal like you did before - you can use method syntax in there as well:

export default {
  func1(a, b) {...},
  func2(a, b) {...}
};

Instead of exporting an object with "static" methods, it would be more reasonable to use named exports here though:

export function func1(a, b) {...}
export function func2(a, b) {...}

which you could import by import * as mod from 'module' if you like to use mod as a namespace.

Share:
11,307
Traveling Tech Guy
Author by

Traveling Tech Guy

I'm a technologist, entrepreneur and developer. I started 3 startups, and currently assist other companies through Traveling Tech Guy - my software consulting company. I specialize in web and mobile development, integration projects, and managing software development projects of various sizes and complexities. I'm always looking for the next challenge, and always eager to learn a new technology/stack/paradigm. Most recently I've been using NodeJS, Express, React and various JavaScript frameworks. Prior to that, I developed in Scala, PHP, and several years of .Net in the enterprise. My mobile experience includes iOS, Android and WP. I've been an avid Stack Overflow user almost from day 1. I'm thankful to the community for helping me out of sticky code situations, and hope that I can contribute back by answering as many questions as I can - on Stack Overflow, Web Applications, Super User, and Android Enthusiasts.

Updated on July 25, 2022

Comments

  • Traveling Tech Guy
    Traveling Tech Guy almost 2 years

    Sorry if question is too simple, but I'm missing something here. Just switched an ES5 module that looked like:

    module.exports = {
      func1: function(a, b) {...},
      func2: function(a, b) {...}
    };
    

    To an ES6 class that looks like this:

    export default class {
      func1(a, b) {...}
      func2(a, b) {...}
    }
    

    And all was well: in both cases I could export mod from 'module'; and call mod.func1(a, b) and mod.func2(a, b).

    However, I have a function that recieves a module function to call:

    var caller = function(func, val1, val2) {
      let a = something(val1);
      let b = something(val2);
      return func(a, b);
    };
    

    When I call caller(mod.func1, x, y) I get the desired result with the first implementation, but an undefined is not a function with the second.

    Printing out the value of mod.func1 returns [Function] in both cases, but clearly something else is returned from an ES6 class.

    What am I doing wrong, and how can I get a class function I can call in another function?

    Update: with the second implementation, I forgot to add the instantiation code:

    import Mod from 'module';
    var mod = new Mod();