Utilizing a closure pattern to compartmentalize my code:
(function(root) {
// MODULE CODE HERE
if (typeof module !== 'undefined' && module.exports) { // CommonJS
/* var dependencies = require(...) */
module.exports = myModule;
} else if (typeof define !== 'undefined' && define.amd) { // AMD
/* var dependencies...; */
define([/* dependencies */], function(/* dependencies */) {
/* Assign closure level vars to respective arguments */
return myModule;
});
} else {
// Dependencies??
root.myModule = myModule;
}
})(this);
For example, using feature detection to accommodate CommonJS modules (such as node.js), AMD or basic global namespace instantiation.
This setup functions properly in node.js; nonetheless, it fails in the browser under certain circumstances. Specifically, when the module contains dependencies. If 'myModule' references an element from another module - like 'super.js' and 'child.js' with their individual definitions - issues arise. For instance, if 'super.js' establishes a method named 'root.super' (where 'root === window' in the browser), attempting 'child.js' to call 'super()' would result in 'super is not a function' error.
What triggers this behavior?
To address this, I attempted altering the order of loading 'super.js' and 'child.js' script elements without success. Subsequently, I experimented with invoking 'child.js' upon document readiness using jQuery:
$(document).ready(function() {
$.getScript('child.js', function() {
// Execute actions involving child, calling super
});
});
Yet again, encountering the same complication. Curiously, inspecting the console reveals that 'super' is indeed accessible and correctly defined.
Why does 'super' within 'child.js' seemingly belong to a distinct scope rather than the expected global one?
Note that omitting the dependency injection segment from the CommonJS export leads to identical errors in node.js (if dependents exist).
EDIT Following @Amberlamps' advice resolved the issue, yet the underlying question persists: What causes this phenomenon? The updated module pattern:
(function(root) {
// MODULE CODE HERE
if (typeof module !== 'undefined' && module.exports) { // CommonJS
/* var dependencies = require(...) */
module.exports = myModule;
} else if (typeof define !== 'undefined' && define.amd) { // AMD
/* var dependencies...; */
define([/* dependencies */], function(/* dependencies */) {
/* Assign closure level vars to respective arguments */
return myModule;
});
} else {
if (root.hasOwnProperty(/* dependencies */)) {
/* var dependencies = root... */
root.myModule = myModule;
}
}
})(this);
This alteration ensures consistent dependencies naming across various environments. However, the query lingers: Why isn't the global object accessible within the closure's scope?
EDIT 2 Through experimentation with RequireJS and AMD, corrections were made to the above code for successful AMD execution. Surprisingly, similar occurrences transpire in this scenario too: Explicitly assigning the global object to a variable within the closure allows it to be acknowledged within said enclosure...