How to get a reference to a class function in ES6?
Asked Answered
A

2

10

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();
Acantho answered 1/8, 2015 at 20:5 Comment(3)
I really doubt that mod.func1(a, b) works with the exported class.Boo
Forgot the instantiation code - now added. Thanks.Acantho
Hm, passing the mod.func1 method as a function to somewhere else requires you to deal with the this context in callbacks problem, but that shouldn't change when switching from an object to a class instance either. Can you show us the body of your function?Boo
T
7
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.

Tunisia answered 1/8, 2015 at 20:13 Comment(4)
Thanks for the suggestion. But if class is just sugar, why the difference in function accessibility?Acantho
Thanks Sean. I updated my question to show the instantiation code - but that didn't work either :(. BTW, if you do want to call a method on the class name, you could add static at the function definition.Acantho
Correct - I'm not able to reproduce this in babel - I get the expected behavior when I instantiate the class. Any more details on how you are compiling / running this (or a more detailed snippet might help too).Tunisia
I'm using Babel to transpile, and the function I had a problem passing a class function into a Passport middleware. The code is too complex to post. But do you say you've managed to get an example like mine working? If so, it must be something I've done wrong.Acantho
B
4

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.

Boo answered 1/8, 2015 at 21:7 Comment(2)
I don't get why everybody thinks they have to use as many ES6 features as possible even if it doesn't make sense. Same for arrow functions... and "suddenly" it does not work as expected.Antechamber
I don't have a problem with it not working - I want to understand why it doesn't work.Acantho

© 2022 - 2024 — McMap. All rights reserved.