Several examples of objects utilizing the identical function as the most recent instance

While working on a new feature for a Javascript library, I ran into an interesting issue. It seems that when a function of an object utilizes a closure and a promise together, all instances of the object end up using the most recently created version. This causes the output of the code snippet below to be "3" repeated three times. However, introducing the var keyword before defining logSecret resolves the problem, resulting in the expected output of 1, 2, 3.

Why is it that multiple instances of the object share the same value?

And what exactly is the role of the var keyword in fixing this issue?

As I'm not yet confident in my understanding of JavaScript to fully grasp the situation, I would greatly appreciate any insights or explanations on what is happening here. Thank you!

function MyObject(myValue){
  var _this = this;
  _this.secret = myValue;
  _this.foo = function() {
    makePromise = function() {
      var promise = $.Deferred();
      promise.resolve("done");
      return promise;
    }
    logSecret = function() {
      console.log(_this.secret);
    }

    var promise = makePromise();
    $.when(promise).then(function (data) { logSecret(); });
  }
}

var obj1 = new MyObject(1);
var obj2 = new MyObject(2);
var obj3 = new MyObject(3);
obj1.foo();
obj2.foo();
obj3.foo();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Answer №1

When variables are not explicitly declared with `var`, `let`, or `const` in non-strict mode, an implicit global variable is created. This means that these variables behave as if they had been declared in the global context.

In this code snippet, the variables `makePromise` and `logSecret` are not explicitly declared, causing them to be shared by every invocation of `MyObject`.

Each time `MyObject` is called, the `makePromise` and `logSecret` variables are overwritten with a new function object instance that closes over the lexical environment for the most recent invocation of `MyObject`.

The last invocation of `MyObject` captures the secret value of `3`, resulting in the observed behavior.


function MyObject(myValue) {
    var _this = this;
    _this.secret = myValue;
    _this.foo = function() {
        makePromise = function() { // global variable
            var promise = $.Deferred();
            promise.resolve("done");
            return promise;
        }

        logSecret = function() { // global variable
            console.log(_this.secret);
        }

        var promise = makePromise();
        $.when(promise).then(function(data) {
            logSecret();
        });
    }
}

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

Determine the daily volume of emails sent from the "no-reply email" address using the Nodemailer library

Our company currently utilizes Nodemailer for internal email communication. Lately, we have been encountering issues with exceeding our daily SMTP relays, resulting in some emails failing to send. To investigate further, I have been tasked with monitoring ...

Mastering the use of expressions in ng-click and ng-show in AngularJS

I've been working on creating expandable rows within a table, but I'm encountering some issues. Despite not receiving any error messages, the functionality isn't behaving as expected. I suspect there might be an issue with how I'm using ...

Incorporating React's dynamic DIV layout algorithm to generate a nested box view design

My goal is to showcase a data model representation on a webpage, depicting objects, attributes, and child objects in a parent-child hierarchy. I had the idea of developing a versatile React component that can store a single data object while also allowing ...

Floating navigation bar that appears and disappears as you scroll

My webpage has a dynamic navbar that consists of two parts: navbarTop and navbarBottom. The navbarTop should appear when the user has scrolled down more than 110 pixels, while the navbarBottom should show up when the user scrolls up. The issue I am facing ...

Having trouble receiving JSON/JSONP correctly

I've been exploring the world of APIs and I'm facing a roadblock right at the beginning. My goal is to extract data from the Fever Public API in order to retrieve a list of subscribed RSS feeds. The API appears to be straightforward - check it ou ...

Displaying multi-dimensional arrays through the console in JavaScript and showcasing their elements

My array is supposed to have 140 indexes in a single format like this: array:[0-140] //however, it currently appears as: array: [ 0: [0-99], 1: [100-140] ] I've confirmed multiple times that it is just one array of objects. Why is it s ...

Highlight the active menu item using jQuery

Check out my menu example here: http://jsfiddle.net/hu5x3hL1/3/ Here is the HTML code: <ul id="menu" class="sidebar"> <li> <a href="#" class="clickme">Menu</a> <ul id="menu1"> <li><a class="dropdown-clas ...

Hiding content and troubleshooting video playback problems in FancyBox

I'm facing an interesting issue. I've implemented FancyBox lightbox to showcase a "video" tag when users click on the image thumbnail, and it functions well with all varieties of HTML5 video. The challenge arises when testing in browsers older th ...

Working with Javascript: Navigating a dynamic array of elements

I need to reorganize a form on my webpage. Currently, all the fields are in one table and I want to move them around based on certain conditions. However, when I try to loop through the elements and move them, the javascript array is changing and causing m ...

Tips for using jQuery to verify the most recent entry in a form

Struggling with this issue - I can't seem to get jquery to function the way I need it to: Essentially, when a user exits a text field, jquery is supposed to capture the input value and respond accordingly: for example, if the user types 'value& ...

Using JavaScript/TypeScript to sort through and separate two arrays

Creating a list of checkboxes on a UI allows users to toggle and filter data results. To achieve this, I am storing the selected checkboxes as a string array. The structure of my code is outlined below: export interface IMyObjectFromAPI { status: { ...

I am encountering the error message "Utils is not defined" while attempting to generate a chart using chart.js

Attempting to replicate the example provided in chart.js documentation : link to example Unfortunately, I am encountering the error: Uncaught ReferenceError: Utils is not defined Despite its simplicity, I am struggling to identify the issue...! ...

Refresh the screen with modifications from the Model using Ajax Post through a javascript function

I am using Ajax to update the model value in my application and I need help showing this new value in the view. Below is the code snippet where I call a method called GetText to update the model value. How can I display the updated model value in the HTML ...

What is the process for choosing corresponding values in jQuery?

Hello, I am a beginner in programming and I am currently working on developing a word guessing game. Here is the code I have written so far: The (letter) represents the key being typed by the player Var compareLetters = $('.letter') represents ...

Vue3 - Managing the Enabling and Disabling of Text Input and Checkbox Based on Input Number

<div class="container-body" v-for="index in 10" :key="index"> <div class="container-content"></div> <div class="container-content"> <input :id="'Row&apo ...

The RefreshIndicator from Material-UI fails to display during the first page load

I am facing an issue with displaying a loading icon during the initial page load. The code appears to be correct to me but for some reason, the loading icon is not showing up. I am utilizing the RefreshIndicator component from material-ui for the loading i ...

The useFormik function does not properly handle the handleSubmit method when used in conjunction with validationSchema

Recently, I attempted to create a registration form using Formik and Yup to handle input errors. However, upon submitting the form, nothing seemed to happen. Interestingly, when I removed the validationSchema, the handleSubmit function worked as expected. ...

Guide to adding the initial element in an array using Immutability Helpers

Looking to rearrange the elements in an array? The challenge is that it involves a link to the object. How can this be achieved using immutability helper? Below you will find my current code: state = { table: [['', '', ' ...

Have you ever wondered why Vue 3 imports all JS files for every page upon the initial project load?

Is there a way to make Vue 3 import only the necessary js files for each component instead of loading all files at once when the project is first loaded? For example, if I navigate to the contact page, Vue should only import the contact.js file, rather tha ...

Uh-oh! It seems like there is a deployment error in NextJS on Vercel. The issue is that Nested

Suddenly, my middleware ceased to function properly during deployment. The error message states: > Build error occurred NestedMiddlewareError: Nested Middleware is not allowed, found: pages/_middleware Please relocate your code to a single file at /midd ...