I do a lot of full-stack JS work, and I generally follow an approach like this when creating a file with encapsulated logic:
export const SOME_KEY_TO_STATE = 'some-key';
export const ANOTHER_KEY_TO_STATE = 'another-key';
let moduleState = {};
export function modifyState(someArg) {
// ... do some logic
// ... perhaps derive some new value based off of logic
const newValue = derivedNewValue;
moduleState[someKey] = newValue;
}
export function getSomeState(aKey) {
// ... do some sanity checking?
const initialValue = moduleState[aKey];
// ... calculate value based on some conditions?
const finalValue = calculatedValue;
return moduleState
}
I've also used classes occasionally, which essentially provide the same structure, except the module state would be inside the class as an instance variable, and possibly static variables for those exported constants:
export default class SomeThing {
static SOME_KEY = '';
state = {};
modifyState(arg) { ... }
getSomeState() { ... }
}
My preferred approach is the first one, primarily because I can import only what I need in other parts of the code without having an entire object floating around (along with it's state and other methods that I may not use <-- is this statement accurate or am I completely off?). Also, if I want to reference functions within a context, I can always do import { * as someName } from myModule
I'm curious though, is there a benefit that I'm not aware of to using a class rather than the first approach I outlined?