Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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();
like image 993
Traveling Tech Guy Avatar asked Aug 01 '15 20:08

Traveling Tech Guy


2 Answers

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.

like image 190
Sean Vieira Avatar answered Sep 21 '22 09:09

Sean Vieira


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.

like image 39
Bergi Avatar answered Sep 21 '22 09:09

Bergi