Exploring JavaScript's Modules, Enclosures, and Scoping

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...

Answer №1

This specific code structure is fully functional. However, if you were to test it using a function named super and invoking it with super(), you may encounter an issue due to super being a reserved keyword. The corrected code snippet functions as intended:

(function(window) {

    window.super = function() {

        console.log("hello");

    };

}) (window);

(function(window) {

    window.super();

}) (window);

To execute your function, utilize window.super(). Attempting to use super() alone will lead to an error.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Customize variable values on-the-fly in Laravel

I am trying to create a navbar in Laravel with Vue.js as a blade.php file. I want to include a variable like {{xyz}} in the navbar, and when I navigate to another page, be able to set text using Vue.js or something similar. Can someone assist me with this? ...

unable to get highcharts to redraw and reflow properly

I am currently working on creating a dynamic page that can display between 1-4 graphs. These graphs need to be able to resize when added or removed from the page. However, I have encountered a major issue with resizing the graphs after resizing the contain ...

Go to a distant web page, complete the form, and send it in

As the creator of Gearsbook.net, a social network for Gears of War players, I am constantly striving to improve the site's functionality. Currently, it is quite basic and in need of updates. One highly requested feature by users is the ability to lin ...

Having trouble with Next.js environment variables not being recognized in an axios patch request

Struggling with passing environment variables in Axios patch request const axios = require("axios"); export const handleSubmit = async (formValue, uniquePageName) => { await axios .patch(process.env.INTERNAL_RETAILER_CONFIG_UPDATE, formVal ...

How can we ensure that the entire BS4 Navbar (on smaller screens) is clickable, allowing users to show/hide the submenu by touching anywhere within the area?

https://i.sstatic.net/03po7.png My goal is to make the entire navbar area touchable, rather than just having a button. I believe this can be achieved by adjusting the default Bootstrap 4 navbar settings: HTML: <nav id="menu-navbar" class="navbar navb ...

Utilizing children as a prop within a Vue component

In React, I can create a FancyList component like this: const FancyList : React.SFC<{},{}> ({children}) => ( <ul> {...children} </ul> ); const FancyListItem : React.SFC<{text: string}, {}> ({children}) => < ...

tag directive not functioning properly

I have encountered an issue while trying to create a simple custom directive. When I specify the directive as <div my-info></div> in my HTML file, it works fine. However, when I specify it as <my-info></my-info>, it does not work. ...

What is the best method for creating a top margin that is dependent on the height of the browser?

Is there a way to make the CSS margin: top; on my HTML main_content element relative to the browser window? I want the main_content to always stay at the bottom of the browser window. How can I achieve this? I attempted the following code, but it didn&apo ...

Personalize the "set up notification" PWA on React

Is it possible to customize this default design, including the picture, title, description, and background? I made changes in manifest.json, but nothing seems to have happened. Here is a picture of the random install prompt that I would like to customize ...

The showdown between AngularJS Directive Restrict A and E

In our small team, we are currently working on a project in AngularJS and striving to uphold basic standards and best practices. Since we are still relatively new to Angular, we have some questions regarding Directives, specifically the `restrict` options. ...

When attempting to use the POST method with a JSON body in Postgresql, I encounter an error

Encountering an error: There seems to be an issue with a JSON token at position 197 while trying to parse it. It occurs in the following code snippet: at JSON.parse () at parse (C:\Users\hp\empServers\node_modules\body-parser&bso ...

Vue.js - Displaying validation errors when a user interacts outside of a component

The ExamEditor Vue component I am working on is quite complex, consisting of sub-components like QuestionEditor and ExerciseEditor. These components are all tied to an exam object that contains nested arrays with questions and more. The layout inside the e ...

Discover local points of interest with the Google Places API integration on your WordPress site through PHP programming

$(document).ready(function() { var image_src = "images/"; var map; var infowindow; var bounds = new google.maps.LatLngBounds(); var PlaceArray = ["restaurant", "cafe", "bar", "grocery_or_supermarket", "parks", "school", "shopping_mall", "movie_t ...

hold on for the arrays to be populated with data from the ajax calls

Currently, I am facing an issue on my page where I need to wait for all data to be loaded and stored in the appropriate arrays before proceeding with any actions. The data retrieval involves three separate AJAX calls, but sometimes the loading process take ...

Unravel and extract information from a JavaScript object using PHP

I am working with a variable called "type" in my code. var type = []; Within this variable, I am using the method push to add an object {'type' : 1}. type.push({'type' : 1}); After performing this operation, I end up with the follow ...

Automatically updating the scope of the .filter() function

Is there a way to update the filter in the code below? .controller('MainCtrl', ["$rootScope", "$scope", function($rootScope, $scope) { $rootScope.number = 1; $scope.text = "foo|baz|bar" }]).filter("MyFormat", ["$rootScope", function($rootS ...

Guide to configuring an x-axis scroll bar for a handsontable

Utilizing the JarvisWidget library to create widgets, I encountered an issue with a table exceeding the width of the widget when using the handsontable library. I attempted to add a scrollbar by setting the CSS width to 100% and adding overflow-x:scroll, b ...

Prevent user input in HTML

Currently, I am working on creating the 8 puzzle box game using JavaScript and jQuery Mobile. The boxes have been set up with <input readonly></input> tags and placed within a 9x9 table. However, an issue arises when attempting to move a box ...

Having difficulty updating an angular variable within a callback function

Currently, I am utilizing the Google Maps directions service to determine the estimated travel time. this.mapsAPILoader.load().then(() => { const p1 = new google.maps.LatLng(50.926217, 5.342043); const p2 = new google.maps.LatLng(50.940525, 5.35362 ...

Using AngularJS to Dynamically Set the Default Selection in a SELECT Element

In my code using JADE syntax, I have the following structure: select(ng-model="eventTypeUI") option(ng-repeat="c in eventUI", ng-value='c.value', ng-disabled='selectEventCanNotBeUsed(c.value)') {{c.name}} ...