I've been using the IIFE
pattern for some modules recently and ran into a problem that I can't seem to find the answer to. In my project, I need to pass a couple of global variables in for usage. One of these is a global googletag
variable which loads in with a default state and then changes once the external code has loaded in.
However, it doesn't seem to update because the pattern doesn't seem to create a reference but a copy. I've simplified the issue to below.
window.globalLevel = 'First';
var Module = (function(_g){
function _stuff(){
return _g;
}
return {
get stuff(){
return _stuff();
}
}
})(window.globalLevel);
// Initial state.
console.log("In Module:", Module.stuff); // "First"
console.log("In Top:", window.globalLevel) // "First"
// After change.
console.log("--- Changing value ---")
window.globalLevel = 'Second'
console.log("In Module:", Module.stuff); // "First"
console.log("In Top:", window.globalLevel) // "Second"
Can I do anything to fix this? What kind of adaptations or considerations should I make? Should I just simply reference the window.globalReference
directly in the module? Seems messy but it does seem to work.
Your _stuff
is currently returning the argument that was initially passed, the _g
. So, when you change the global variable with window.globalLevel = 'Second'
, the argument does not change, so the original argument is what gets echoed back. You can fix it by returning window.globalLevel
:
window.globalLevel = 'First';
var Module = (function(){
function _stuff(){
return window.globalLevel;
}
return {
get stuff(){
return _stuff();
}
}
})(window.globalLevel);
// Initial state.
console.log("In Module:", Module.stuff); // "First"
console.log("In Top:", window.globalLevel) // "First"
// After change.
console.log("--- Changing value ---")
window.globalLevel = 'Second'
console.log("In Module:", Module.stuff); // "First"
console.log("In Top:", window.globalLevel) // "Second"
If window.globalLevel
were an object and not a primitive, both the global variable and the argument would reference the same underlying object in memory, in which case your _g
would work:
window.globalLevel = { value: 'First' };
var Module = (function(_g){
function _stuff(){
return _g.value;
}
return {
get stuff(){
return _stuff();
}
}
})(window.globalLevel);
// Initial state.
console.log("In Module:", Module.stuff); // "First"
console.log("In Top:", window.globalLevel.value) // "First"
// After change.
console.log("--- Changing value ---")
window.globalLevel.value = 'Second'
console.log("In Module:", Module.stuff); // "First"
console.log("In Top:", window.globalLevel.value) // "Second"