What causes the scope to shift when incorporating a Lazy function within the module pattern in JavaScript?

Implementation 1:

Working code in normal


var foo1 = function() {
    var t1 = new Date();
    console.log("initialize - one time only " + this);
    foo1 = function() {
        console.log("Executes every time after initializing (initialize should not execute again) " + this);
        return t1;
    };
    return foo1();
};

Executing: foo1();

Output:

First Time

Initialize - one time only [object Window]

Executes every time after initializing (initialize should not execute again) [object Window]

Every Other Time

Executes every time after initializing (initialize should not execute again) [object Window]

Implementation 2

Trying the same in a JavaScript module


var tt=(function(){
     var foo = function() {
        var that=this;
        var t = new Date();
        console.log("initialize - one time only" + this);
        foo = function() {
            console.log("Executes every time after initializing(initialize should not execute again) "+this);
            return t;
        };
        return foo();
    }
    return {
        foo:foo
    };
})();

Execute: tt.foo();

Output:

First Time

Initialize - one time only [object Object]

Executes every time after initializing(initialize should not execute again) [object Window]

Every Other Time

Initialize - one time only [object Object]

Executes every time after initializing(initialize should not execute again) [object Window]

Why does foo1 initialize again in method 2?

Why does the scope of this change inside the module pattern to window in method 2?

How can we make method 2 work like in method 1?

Please provide a conceptual explanation of what is wrong with method 2. Thank you in advance.

Answer №1

These lines are visible:

initialise - one time only[object Object]
Executes everytime after initialising(initialise should not execute again) [object Window]

every time you call tt.foo() because the original reference to foo is stored in the return object ({ foo: foo }); Therefore, what actually gets executed is different from reassigning the function itself.

but you're executing:

function () {
    var that=this;
    var t = new Date();
    console.log("initialise - one time only" + this);
    foo = function() {
        console.log("Executes everytime after initialising(initialise should not execute again) "+this);
        return t;
    };
    return foo();
}

The log shows

initialise - one time only[object Object]
since the method is called with the context of the:

{ foo: foo }

To clarify, it's similar to calling:

var a = {
   test: function () {
      console.log(this);
   }
}

In the second console.log, foo is not referenced by the anonymous object ({ foo: foo }), so it ends up being called with context window - equivalent to foo.apply(window). I hope this explanation is clear.

Edit To ensure the second method works like the first, you need to establish the correct reference for foo upfront. The following code rectifies the issue:

var tt=(function(){
     var foo = (function() {
        var that=this;
        var t = new Date();
        console.log("initialise - one time only" + this);
        foo = function() {
            console.log("Executes everytime after initialising(initialise should not execute again) "+this);
            return t;
        };
        return foo;
    }());
    return {
        foo:foo
    };
})();

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

Receiving multiple NodeJS Responses through AJAX for a single request

I have been working on a WebApp that involves heavy AJAX calls from the frontend and NodeJS Express at the backend. Here is a glimpse of my Frontend Code- Below is the global AJAX function I consistently use in all my projects: function _ajax(params = {}, ...

Incorporate a different address using $location.path(path); and submit the ng-form

I have a form: <form name="myForm" ng-submit="save(myObject)"> ... <button type="submit" class="btn btn-primary" ng-click="changeLocation('/railway-connection')">Save </button> </form> My goal is to perform two actions w ...

Create custom components by wrapping npm components and exporting them as a single custom component

Encountering issues while installing 3rd party components from npm. For instance, a dropdown react module that can be used easily in my own module; however, I find myself needing to declare its style and other dependencies in multiple modules. For example ...

What are some ways to design scrollbars with a Google Wave-like style?

Is there a way to design scrollbars similar to the ones found in Google Wave? They seem to save space and have an appealing look. I am interested in implementing these customized scrollbars on a div element, just like how Google Wave utilizes them. https: ...

Display a custom AngularJS directive on content loaded through $http request

I'm facing a dilemma. I have created a directive app.directive('a', function() { return { restrict: 'E', link: function(scope, elem, attrs) { elem.on('click', function(e){ ...

Using discord.js to conveniently set up a guild along with channels that are equipped with custom

When Discord devs introduced this feature, I can't seem to wrap my head around how they intended Discord.GuildManager#create to function. How could they possibly have expected it to work with Discord.GuildCreateOptions#channels[0], for instance, { ...

Identifying when two separate browser windows are both open on the same website

Is it possible to detect when a user has my website open in one tab, then opens it in another tab? If so, I want to show a warning on the newly opened tab. Currently, I am implementing a solution where I send a "keep alive" ajax call every second to the s ...

Guide to implementing the collapsible start and stop button feature in Angular

Having an issue in my Angular application with the dashboard page. I've created a button for start or stop (toggle functionality) but it's not working as expected. .component.ts toggleCollapse(jammer) { this.jammer.isCollapsed ? 'START& ...

When trying to load AJAX, it does not function properly unless the page is refreshed

I'm currently working on a web page and encountering some difficulties. Within my HTML, I have two divs that are refreshed using AJAX. The issue is that the content loading seems to be inconsistent unless I manually refresh the page or implement a tim ...

JavaScript Scroller that keeps on scrolling

Unique Continuous JavaScript Scroller I am currently working on a JavaScript scroller script that enables left to right and right to left scrolling on the click of next and previous buttons. The script is designed to work with 1 to 3 div elements in a con ...

Why is my code executing twice rather than just once?

` import './App.css'; import ArrayState from './components/ArrayState'; import FetchApi from './components/FetchAPI/FetchApi'; import Login from './components/Login'; import Useeffect2 from './components/Use ...

What is the most efficient method for transferring session data from a Client component to a server component in NEXT.js version 13 and beyond?

Currently, I am working on a web application that requires passing session?.user?.email from the useSession() function in next-auth/react to a server-side component. This server-side component will then execute a fetch request to /api/users/email/ to deter ...

Unable to establish API connection in node.js

As a novice, I recently delved into the world of APIs using node.js. My goal was to fetch data from a simple API for practice. This venture is just an experiment and any assistance or guidance on connecting to APIs, especially those requiring an API key, ...

What is the best way to iterate through elements that come after a specific element?

I'm confident that I will be able to provide an answer to this very soon... Here's a sample code snippet: <script> function ClearAndRunFuncs(element) { //Clears responses for elements AFTER this element with an onchange //Executes the uni ...

Using API call responses to initiate a render in React

As a newcomer to React, I'm facing an issue with passing the results of my API call to another component file in order to trigger a render. Can anyone provide a straightforward explanation of what steps I need to take? In my code, I make a call to th ...

Through the implementation of JavaScript, the element's class is dynamically altered

While working on my project, I encountered an issue with implementing a change in the class of an element using JavaScript. The problem is that when I click on the home page, the last page does not get deselected. Here is my current JavaScript code: const ...

Oops, looks like there's been an issue with the webpack build. It seems we're

I encountered an issue while building and running the development server using Webpack. My project is based on Vue.js, and I utilized vue-cli to generate it. Jest is used for testing, and running npm test poses no problems. However, when I run npm run bui ...

What benefits does NewRelic offer?

We are looking for a way to monitor events within our application and send the data to a monitoring server such as NewRelic. Our goal is to set up alerts based on this custom data. For instance, we would like to receive an alert if an event does not occur ...

The server encountered an unexpected error while processing the request, possibly due to a

My JavaScript file includes an interval function that calls the following code: setInterval(function() { $.getJSON('/home/trackUnreadMsgs', function(result) { $.each(result, function(i, field) { var temp = "#messby" + result[i].from; ...

Automatically populate a div with content from a file

As I am completely new to the world of HTML, I find myself in need of quickly putting together something for work just as a proof of concept. I apologize if this question has been answered previously, but honestly, I wouldn't even know how to start se ...