Es6 Modules: Export Single Class of Static Methods or Multiple Individual Methods

ES6 modules: Export single class of static methods OR multiple individual methods

A class of just static methods feels like a bit of a 'code smell'

Yes indeed. You don't need a class structure here! Just export a normal "module" object:

//------ myMethods.js ------

export default {
myMethod1() {
console.log('foo');
},
myMethod2(args...) {
console.log('bar');
}
};

I do recommend your second approach with multiple exports, though.

exporting everything individually does feel a bit verbose

Well, you don't need any wrapper structure, so I'd say it's less boilerplate. You just have to explicitly tag everything that you want to be exported, which is not a bad thing.

* as syntax is my preferred method as it allows you to use the dot notation (referencing both the module AND the method) aiding code readability.

That's very much personal preference, and does depend on the type of code you are writing. Sometimes conciseness is superior, but the ability to explicitly reference the module can be helpful as well. Notice that namespace imports using * as and default-imported objects are very similar here, though only named exports allow you to directly reference them via import {myMethod1, myMethod2}. So better leave the choice to those that import your module.

Does this have any performance implications?

Not much. Current ES6 implementations are not yet aiming for performance optimisations anyway.

In general, static identifiers are easier to resolve and optimise than property accesses[1], multiple named exports and partial imports could theoretically make JIT faster, and of course smaller files need less time to load if unused exports are removed during bundling. See here for details. There hardly will be noticeable performance differences, you should use what is better maintainable.

[1]: module namespaces (import * as ns) are static as well, even if ns.… looks like a dynamic property access

How can I export static function in ES6?

You can alias the static function as a normal function

export const ThisIsStaticFunction = Something.ThisIsStaticFunction;
export default Something;

import {ThisIsStaticFunction}, Something from 'xxx';

Usually in Javascript (unlike Java) you can use plain function over static function.

export function ThisIsAFunction() {}

export default class Something {
instanceMethod() {
const result = ThisIsAFunction();
}
}

import {ThisIsAFunction}, Something from 'xxx';

const foo = ThisIsAFunction();
const bar = new Something()
const biz = bar.instanceMethod();

Class with static methods vs exported functions typescript

Functionally, both implementations will produce the same result with the only difference being that for static methods the function is attached to the class' prototype. If you don't actually need that behavior (unlikely that you do), I'd keep you static methods as separate functions as this is better for tree-shaking and code-splitting (unless you have a LOT of static methods though, these will be only minor gains). In practice, I find that static methods usually only appear for two reasons: (1) whoever wrote the code is used to Java and (2) some IDEs present warnings that you should mark methods as static if they don't use instance variables.

If you just want that ability to namespace a bunch of static methods, you can still do so by exporting an object with all of the individual functions attached.

Split ES6 Class in multiple files to import individual methods of a library

I have experimented a bit more:

This i what I`ve been come up now:

// helperUtils/stringUtils.js
import { helperUtils } from '../helperUtils.js';

helperUtils.prototype.stringUtil1 = (str) => {
return str += ' this is very helpful!';
}

export const stringUtils = helperUtils.prototype;

Now the stringUtils prototype won't override my helperUtils prototype and I can safely import single methods to my main class.

If anyone got a better solution please share it with us!

Thanks so far!

How can I export static class methods without exporting the whole class

Since they are static methods, they are basically just properties on the class object. Since that is the case, you can just export them one by one:

export default class Cookies {
static get (name) {...}
static set (...) {...}
static remove (...) {...}
}

export const get = Cookies.get;
export const set = Cookies.set;
export const remove = Cookies.remove;

How to break static methods out to their own file and export correctly via ES6?

With an ES6 class, you can assign to the class object and have what is essentially a static method, just like what you'd do in ES5:

class Door {
constructor() {
this.species = 'Oak';
this.instanceMethod = fnInstanceMethod; // <-- works great
}
}
Door.create = fnCreate;

Note that your

this.instanceMethod = fnInstanceMethod; // <-- works great

while it works, it's probably not the best idea - if you want to imitate standard inheritence from the prototype (like when separating things out over multiple files isn't needed), you should assign to the prototype object instead, just like in ES5:

class Door {
constructor() {
this.species = 'Oak';
}
}
Door.create = fnCreate;
Door.prototype.instanceMethod = fnInstanceMethod;

I'm not sure about the "Door is not a constructor" error you're having, but with your current implementation, fnCreate (in a separate file) won't have scope of Door, so fnCreate won't be able to reference and create a new Door. One way to solve this would be to export a function that takes Door as an input, and returns a function that returns an instance:

// makeCreate.js
module.exports = theClass => () => new theClass();

// Door.js
const makeCreate = require('./makeCreate');
const fnInstanceMethod = require('./instanceMethod');
class Door {
constructor() {
this.species = 'Oak';
}
}
Door.create = makeCreate(Door);
Door.prototype.instanceMethod = fnInstanceMethod;

module.exports = Door;

Or, the makeCreate in ES5:

function makeCreate(theClass) {
return function() {
return new theClass();
}
}
module.exports = makeCreate;

import class and call static method with es6 modules with babel transpiler

You have two options:

  1. Export EmberReflux like you are doing:

    export { EmberReflux };

    and then import it like:

    import { EmberReflux } from '../utils/ember-reflux';
  2. Use default when exporting:

    export default EmberReflux;

    and import it (like you are doing):

     import EmberReflux from '../utils/ember-reflux';

In both cases you can then use your EmberReflux like:

EmberReflux.createActions();

export / import single class method using ES6 modules?

You would have to export it on the prototype. But remember that if you do that you won't call the function in the class/object context:

export foo.prototype. fooMethod

However I would recommend you to not to do so.


Okay, due to your comment you want a good way to have a common functionality for two classes, that don't extend the same base class. One simple way is to import a utility function from two classes:

foo.js

export function foo() {
return this.name;
}

a.js

import {foo} from 'foo';
export class A extends BaseA {
foo() {
foo.apply(this, arguments);
}
}

b.js

import {foo} from 'foo';
export class B extends BaseB {
foo() {
foo.apply(this, arguments);
}
}

This is a good pattern and works well for a single function, but has limits if you want to apply more complex functionality. A good way to achieve this is a mixing pattern:

foo.js

export default superClass => class extends superClass {
foo() {
return this.name;
}
};

a.js

import foo from 'foo';
export class A extends foo(BaseA) {
..
}

b.js

import foo from 'foo';
export class B extends foo(BaseB) {
..
}

This will make your mixing create a new anonymous class between your class 'A'/'B' and 'BaseA'/'BaseB', which provides the common function foo.



Related Topics



Leave a reply



Submit