What exactly is the explanation behind this behavior in JavaScript when it comes to pass-by-reference

As a newcomer to JavaScript, I came across an intriguing problem that made me question what would be displayed on the console. The correct answer turned out to be 4 4 4 4, thanks to pass-by-reference. Still, I'm struggling to grasp why this is the outcome. How does pass-by-reference come into play when the output seems to solely rely on the value of i within a simple for-loop iteration?

const array = [10, 21, 31, 41];

for(i = 0; i < array.length; i++) {
  setTimeout(function print(array){
      console.log(i)}, 3000);
}

Answer №1

Let's break it down step by step:

const array = [10, 21, 31, 41];

for(i = 0; i < array.length; i++) {
  setTimeout(function print(array) { /* stuff... */ }, 3000);
}

// By the time we reach this point, the value of i is 4.

When running this code snippet, we are looping through the array and setting a timeout for each iteration. At the end of the loop, setTimeout has been called four times, but none of the functions provided have executed yet. They will only execute after another 3 seconds.

Crucially, at this stage, the value of i is 4.

Three seconds later...

Finally, the function print passed to setTimeout will run. What does this function actually look like?:

function print(array) { console.log(i); }

Now consider that i is currently 4. Therefore, it will print 4, repeating four times. This is because the function reads the current value of i when it is executed, not when it was defined initially.

In essence, i holds the value 4 when the function print is triggered, resulting in the output of 4.

Answer №2

Take another look at the inner function that is triggered by the timeout.

function display(numbers){
    console.log(i);
}

The array provided is not actually utilized at any point, as demonstrated by the fact that the code below produces the same output (4 4 4 4):

for(i = 0; i < numbers.length; i++) {
  setTimeout(function print(){
      console.log(i)}, 3000);
}

Due to pass by reference behavior, the value of i passed into the print() function is a reference to whatever i holds when console.log(i) is executed. With a 3-second delay, the loop completes before console.log(i) is called, resulting in i equalling 4. Even changing the value of i after the loop affects the outcome:

for(i = 0; i < 4; i++) {
  setTimeout(function display(){
      console.log(i)}, 3000);
}

i = "bar";
// outputs bar bar bar bar

Answer №3

Utilizing setTimeout in your code introduces asynchronicity - after the 3000 millisecond timeout, the JavaScript loop may end prematurely resulting in the last value of the index being taken, such as the number 4. Explore 'js Eventloop' to gain a deeper understanding of how browsers operate at a fundamental level.

Answer №4

Only one value is assigned to i. The original value is not stored when setTimeout is called.

The value of i will be 4 when the print function is executed after the for-loop completes, as that is the final value at the end of the loop.

Answer №5

In order to access the 'i' value, one must understand the concept of closure. As the function is executed, the 'i' value changes to 4 and is then printed.

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

Experiencing a lack of data within the local storage feature of ReactJS

I'm encountering an issue where, upon clicking the submit button, my local storage remains empty even though I have data in my array of objects. Despite assigning values to the localArray variable using titleDesMap, the data is not being stored in th ...

Persistently Undefined Angular Attribute

I have been trying to dynamically bind a CSS class using an AngularJS function. While the functionality is working properly, I keep encountering numerous errors in the browser console. Can anyone offer assistance with this issue? I have included my code an ...

Is it possible to utilize hooks such as 'useState' within an async/await server component?

'use client' async function Teachers (){ const response = await fetch('http://localhost:8000/teachers', }) const data = await response.json(); const [showNames , setShowNames] = useState(false); // Unable t ...

When utilizing Express and passport, an error occurs stating that req.isAuthenticated is undefined

After successfully setting up a backend express server in the past few hours, I decided to implement authorization by following a tutorial. The login functionality works perfectly, but when attempting to access /authrequired (a restricted page that require ...

Adding a question mark at the top of the content in a txt file using node.js's

When I use the fs.readFile() function to retrieve data from a .txt file, I notice that the content begins with "?Alex libman". Here is the code snippet: fs.readFile(__dirname+"/txts/generate/titles0.txt", "utf-8", function (ex, titles) { var titlesArr = ...

Using AJAX to dynamically edit and update PHP data

The information displayed on my index.php page is fetched from a database using the mysqli_fetch_array function. The data is presented in a table format with fields like Name, Age, Email, and Update. An edit button allows users to modify the data. Here is ...

Name or Title of a Polygon/Polyhedron Using Three.js

My page contains a sample code that successfully retrieves the name of an object when a user clicks on it. However, the code works well with cubes and spheres but fails with polygons. To see how the clicks respond, you can check the console logs. What shou ...

Is there a way to use a component in two separate stack navigator screens without losing their distinctiveness?

Suppose we have the following scenario: <Stack.Screen name="Home" component={BottomTab} options = {{title:'Home', headerShown: false}} /> <Stack.Screen name = 'Create' component={BottomTab} option ...

The div is set to a position of absolute, causing the overflow-y property to be set to auto. As a

I am facing an issue with a div that has absolute positioning nested inside other divs. If you take a look at the code snippet below from http://jsfiddle.net/d8GYk/, you'll notice the styling properties applied to the div. <div style="position: ...

I'm looking to enhance my code by adding a new user login password. How can I achieve this?

Currently, I am in the process of adding another user and have been exploring various code snippets available on different websites. I decided to test the following example, which worked perfectly. However, I am now wondering how I can add an additional u ...

Enhance TinyMCE functionality to permit text as a primary element within <table> or <tr> tags

I've been struggling for the past three hours, trying out different solutions and searching like crazy on Google. Unfortunately, I have not been able to find a resolution to this particular issue. Issue: TinyMCE is not allowing me to insert text dire ...

The Jquery script is ineffective for newly added elements

After creating an Ajax Form that functions well, I noticed that when the result of the form is another form, my script does not work for the new form generated. Is there a way to make the new form function like the old one? $(document).ready(function() ...

Creating a dynamic slider using jQuery

Here is the code snippet I have been working on: var current_slide = 1, animation_time = 1000, pause = 3000, slide_container = $('.slide_container'), interval, height = slide_container.height(), slides ...

variable value remains constant after being updated

Here is the code snippet I am working with: function change(initial) { let a = initial; console.log(a); return [ a, (v) => { a = v; } ]; } const [val, setter] = change("initial"); console.log(val); setter("s&qu ...

Is it possible to use reactjs and react-router to showcase either a component or {this.props.children}?

Here's the scene: I have multiple components where certain words can be clicked to link to a reference page/component. If the highlighted words are not clicked, the component is displayed as is (and there are many of them with this feature and a menu ...

Turning off form validation in AngularJS for a short period of time

Successfully implemented client side form validation using AngularJS, but now I want to test my server side validation by sending incorrect data. However, AngularJS is preventing me from doing so! Is there a way around this without disabling Javascript an ...

Error encountered with Firebase when integrating Firestore into a NextJS application

For my project, I have successfully implemented authentication using Firebase. However, when I attempt to use Firestore in my app, I encounter an error prompting me to initialize my app. I already have a file for this purpose where I import all the necessa ...

Difficulty encountered when transferring an array from Xcode to JavaScript via SBJSON

In an attempt to transfer an array from Xcode to a local HTML file, I am utilizing jQuery in the HTML code. This involves using loadHTMLString: with baseURL to read both the HTML and included .js files. However, I am encountering an issue when trying to us ...

The encoding of characters in the JQuery .html method

I am facing a similar issue as described in this jQuery AJAX Character Encoding question, but none of the solutions mentioned there seem to work for me. To demonstrate the problem, I have created three simple files: PHP File: //prueba.php echo "nº one ...

Having issues with jQuery setinterval not functioning properly? Looking for solutions to resolve this problem?

JavaScript Issue: $(document).on('mouseover', '.image_slider', function() { setInterval(slider(this), 10000); }); function slider(that){ console.log(that); } I am facing some trouble with this code. Can anyone help me figure out ...