Reputation: 25
I have a module to set config. It's working. I want to get config using same module. I don't want to use additional file.
I tried a code something like that:
let config_defaults = { test_option: false };
let active_config;
if(active_config === undefined){ active_config = config_defaults };
exports.getcfg = active_config;
const setcfg function(options){
options = Object.assign({}, config_defaults, options);
active_config = options;
return(options);
}; exports.setcfg = select_config;
setcfg
returns changes with no problem. But I can't get changes at getcfg
. Is it possible to get changes without using additional file?
Outputs:
console.log( testmodule.setcfg({test_option: true}) ); /* >> Output: { test_option: true } */
console.log( testmodule.getcfg ); /* >> Output: { test_option: false } */
Upvotes: 1
Views: 100
Reputation: 53370
You can totally replicate the Java getter/setter behaviour with JavaScript class:
const config_defaults = {
test_option: false
};
/*export*/ class ConfigManager {
activeConfig = config_defaults;
getActiveConfig() {
return this.activeConfig;
}
setActiveConfig(options) {
options = Object.assign({}, config_defaults, options);
this.activeConfig = options;
return options;
}
}
// import { ConfigManager } from "./testmodule";
const configManager = new ConfigManager();
console.log(configManager.setActiveConfig({
test_option: true
})); // >> Output: { test_option: true }
console.log(configManager.getActiveConfig()); // >> Output: { test_option: true }
With JavaScript, you do not necessarily need to use a class, especially for a singleton; in this case, an object is enough:
const config_defaults = {
test_option: false
};
/*export*/ const configManager = {
activeConfig: config_defaults,
getActiveConfig() {
return this.activeConfig;
},
setActiveConfig(options) {
options = Object.assign({}, config_defaults, options);
this.activeConfig = options;
return options;
}
};
// import { configManager } from "./testmodule";
console.log(configManager.setActiveConfig({
test_option: true
})); // >> Output: { test_option: true }
console.log(configManager.getActiveConfig()); // >> Output: { test_option: true }
Still with JavaScript, you can even hide the getter/setter pattern:
const config_defaults = {
test_option: false
};
/*export*/ const configManager = {
_privateActiveConfig: config_defaults,
get activeConfig() {
return this._privateActiveConfig;
},
set activeConfig(options) {
options = Object.assign({}, config_defaults, options);
this._privateActiveConfig = options;
return options;
}
};
// import { configManager } from "./testModule";
console.log(configManager.activeConfig = {
test_option: true
}); // >> Output: { test_option: true }
console.log(configManager.activeConfig); // >> Output: { test_option: true }
Upvotes: 1
Reputation: 53370
The cause of the issue is that you already assign the reference to an active_config
object when defining exports.getcfg
, but later in setcfg
, active_config
is re-assigned a reference to
a different object.
You could compare the assignment to an object reference as writing down the address of that object in a variable. If you re-assign active_config
, all other variables that knew its previous address still reference that old content.
See e.g. Is JavaScript a pass-by-reference or pass-by-value language?
You have 2 easy solutions:
Perform a deep mutation: instead of re-assigning the content of active_config
directly, you change the value of one of its members, as if it was a "routing switch"
Make the getter a function, which can then use the most recent version of the scope variable when executed
const exports = testmodule = {};
const config_defaults = {
test_option: false
};
// Option 1: expose a switch instead of directly the changing variable
const active_config_switch = {
active_config: config_defaults,
};
exports.getcfg_switch = active_config_switch;
// Option 2: getter as a function
let active_config = config_defaults;
exports.getcfgFn = function() {
return active_config;
}
const select_config = function(options) {
options = Object.assign({}, config_defaults, options);
active_config_switch.active_config = options; // Option 1: deep mutation
active_config = options;
return options;
};
exports.setcfg = select_config;
console.log(testmodule.setcfg({
test_option: true
})); /* >> Output: { test_option: true } */
// Option 1: read the deep member
console.log(testmodule.getcfg_switch.active_config); /* >> Output: { test_option: true } */
// Option 2: execute the getter function
console.log(testmodule.getcfgFn()); /* >> Output: { test_option: true } */
Upvotes: 0