Looping through an object

I stumbled upon this code snippet that adds a specific property value of all blocks in a nested object to an arrays array. I'm having trouble understanding how iteration is achieved in a nested object like the one shown below using a for loop.

Could someone please clarify how the for loop iteration works with an object?

let list = {
   value: 1,
   rest: {
      value: 2,
      rest: {
         value: 3,
         rest: null
    }
  }
};

Here is the function responsible for this operation

function listToArray(list) {
  let arrays = [];
  for (let node = list; node; node = node.rest) { // my main question: how does this work?
    arrays.push(node.value);
  }
  return arrays;
}
console.log(listToArray(list)); // -> [1, 2, 3]

Answer №1

Understanding the functionality of for loops:

Before delving into the intricacies of for loops, it's essential to grasp their underlying mechanism.

The for statement establishes a loop that comprises three optional expressions enclosed in parentheses, separated by semicolons, followed by a statement (typically a block statement) to be executed within the loop. MDN

The structure of the for loop is as follows:

for ([initialization]; [condition]; [final-expression])
   statement

The expressions initialization, condition, and final-expression can be any valid expressions. Any or all of these expressions can be omitted (for(;;) is valid in JavaScript and results in an infinite loop).

The execution of a for loop commences by performing the initialization expression if it is specified. Subsequently, it iterates through the following steps: checking if the condition is true, executing the statement(s) and final-expression in sequence if the condition is true, and halting the loop if the condition is false.

For instance, consider the diagram below (image source):

https://i.sstatic.net/dr2hY.png

This diagram corresponds to the for loop presented below:

for(i = 2; i <= 6; i = i + 2)
  print i + 1

It is notable that the initialization part i = 2 is executed only once, while the remaining parts (the condition, the statement(s), and the final-expression) can be executed multiple times (in order) based on the condition.

Elucidation of the provided code snippet:

for (let node = list; node; node = node.rest) { // big question: how it works or possible?
  arrays.push(node.value);
}

The initialization segment of this loop declares the variable node and sets its value to the root element list. This segment is executed only once, at the beginning of the loop.

The condition part verifies whether node (the variable) is truthy or not. In JavaScript, an object is truthy while undefined is falsy. The objective of the loop is to traverse through the object from node to node (as demonstrated in the final-expression section below). When there is a child node, the subsequent value of node will be that node (truthy value), leading to a true condition. Conversely, if the child node does not exist, node will be undefined (falsy value), resulting in a false condition.

The final-expression simply assigns the value of node to the child node of the current node, denoted as node.rest. When this child node exists, node is an object; otherwise, it becomes undefined.

Answer №2

Explaining the components of a for loop

  1. Initialization - executed once (let node=list)
  2. Continuation condition - checked on each iteration (node)
  3. Next step - triggers when condition in 2 is true. Typically involves updating a variable from 1

Let's dive deeper into the process:

for(let node = list; node; node=node.rest)

Initially, a new variable node is created with the value of list
Then, it's verified that the node is not null or undefined. These falsy values result in false when coerced to boolean. If not falsy, arrays.push is executed, else the loop ends.
After that, node is updated with node.rest. Before arrays.push is executed with the new node, the condition is checked.
Ultimately, when node reaches

{
   value: 3,
   rest: null
}

step 3 of the loop updates node by assigning null to it. As a result, 2 fails and the loop is terminated.

Answer №3

To start off, let's look at the syntax of a for loop:

for (statement 1; statement 2; statement 3) {
    // code block to be executed
}
  1. Statement 1 is executed (once) before the code block runs.
  2. Statement 2 sets the condition for running the code block.
  3. Statement 3 is executed (each time) after the code block has run.

During each iteration, you go deeper into the tree with node = node.rest. The loop ends when you try to access the rest property on a node that either doesn't have that key or it's set to null. This results in the value being undefined or null, both of which are considered false values in Javascript, causing the loop to stop.

Here's an example with debugging:

let list = {
   value: 1,
   rest: {
      value: 2,
      rest: {
         value: 3,
         rest: null
    }
  }
};

function listToArray(list)
{
    let arrays = [];
    
    for (let node = list; node; node = node.rest)
    {
        console.log("Current node is: " + JSON.stringify(node));
        console.log("Node value is: " + node.value);
        arrays.push(node.value);
        console.log("Next node will be: " + JSON.stringify(node.rest));
    }

    return arrays;
}

console.log(listToArray(list));

Answer №4

You have the option to make this process recursive, which can simplify the explanation.

If the object is null, the array is returned as is. Otherwise, a call to the next rest is made and the value is added to the array.

obj = { value: 1, rest: {...} }, arr = []          // Add 1 to arr and return obj.rest
obj = { value: 2, rest: {...} }, arr = [ 1 ]       // Add 2 to arr and return obj.rest
obj = { value: 3, rest: null  }, arr = [ 1, 2 ]    // Add 3 to arr and return null
obj = null,                      arr = [ 1, 2, 3 ] // Return arr [ 1, 2, 3 ]

let list = {
  value: 1,
  rest: {
    value: 2,
    rest: {
      value: 3,
      rest: null
    }
  }
};

function listToArray(obj, arr = []) {
  return obj == null ? arr : listToArray(obj.rest, arr.concat(obj.value));
}

console.log(listToArray(list)); // -> [1, 2, 3]
.as-console-wrapper { top: 0; max-height: 100% !important; }

Answer №5

for is like a shortcut for while, even though they are essentially the same with only a few minor differences:

for (let i=0; i<10; i++) {
  console.log(i);
}

let i=0;
while(i<10) {
  console.log(i);
  i++;
}

The structure of for is

for(initialization, test, iteration)
. For example:

for (let node = list; node; node = node.rest) { doSomething(node); }

Can be interpreted more plainly like this:

let node = list;
while(node) { 
  doSomething(node);
  node = node.rest;
}

Answer №6

If you're looking to access the nested object that contains value: 3, you can do the following:

 list.rest.rest // { value: 3, rest: null }

Alternatively, you can break it down into multiple lines like this:

 let node = list; // { value: 1, rest: { ... } }
 node = node.rest; // { value: 2, rest: { ... } }
 node = node.rest; // { value: 3, rest: null }

This process can be adapted for any number of repetitions using a loop:

 for(let node = list; node; node = node.rest) {
   //...
 }

Here's a real-world analogy:

Imagine you live in a small village with houses lined up along a single street from north to south. You live at the northern end, with Bob living next to you, and further down is Alice followed by Eve. To walk along the street to visit each house, you could go from Bob to Alice to Eve, or simply walk to the next house until you reach the end of the village.

 const bob = you.southernNeighbour;
 const alice = bob.southernNeighbour;
 const eve = alice.southernNeighbour;

 // ...

let current = you; // start where you are
while(current) // keep walking as long as there are houses 
  current = current.southernNeighbour; // move to the next southern neighbour

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

sending information back to a middleware using a resolved promise

As a newcomer to nodejs, I am facing an issue with retrieving data from a function that returns a promise. The response from the middleware needs to be sent back to the front end. Below is the relevant code snippet: // Middleware app.get('/player&apo ...

Align dropdown navigation menu/sorting dropdown in the same position as the button

Exploring the world of dropdown menus in CSS has led me to encounter some challenges. I am striving to ensure that the dropdown boxes appear on the same line as the button that triggers them. Below is the CSS code I have been working with: /* global style ...

retrieve a string from a given array

I need to retrieve a string from an array in vue and display it on the screen. Here is the method I created for this purpose: displayFixturesName() { const result = this.selectedFixture.toString(); document.getElementById(& ...

Can a Handlebar variable be accessed using an external .js file?

Hello there! Despite the ongoing pandemic, I hope you are doing well. Currently, I'm deep into a school project and seem to have hit a roadblock that I can't maneuver around. My main dilemma lies in finding a way to access the data communicated b ...

"Exploring the Mini Drawer feature on Material UI brings up a whole new page for the Link

Currently, I am working on a project that involves updating stocks using Material UI. I have implemented a mini drawer from Material UI, but when I click on the menu link, it routes to a new page instead of rendering on the homepage itself. In my App.JS f ...

Organize information in a React table following a predetermined sequence, not based on alphabetical order

As a beginner with React, I'm looking to sort my data by the column "Status" in a specific order (B, A, C) and vice versa, not alphabetically. The data structure looks like this: export interface Delivery { id: number; name: string; amount: num ...

What is the process for updating information in Vue.js?

I need assistance with displaying the updated data in a modal. When I trigger the testing(data) function through a click event, the data appears correctly within the function. However, the template does not update and still shows the previous data. How can ...

Ensure that the textbox remains safe from accidental keyboard inputs

How can I ensure that users can only select a date from the calendar control in my textbox, rather than typing it manually, even if I make the textbox read-only? ...

What is the best way to halt a window.setInterval function in JavaScript?

I have a JavaScript function that runs every 2000ms. I need to find a way to pause this function so that the user can interact with other elements on the page without interruptions. Is there a way to achieve this? Below is the code for the function: win ...

Material UI React Autocomplete Component

I'm currently working on integrating an Autocomplete component using the Material UI library. However, I've encountered a challenge - I'm unsure of how to properly pass the value and onChange functions, especially since I have a custom Text ...

What causes one CSS file's properties to be inherited by another CSS file in a React application?

I'm puzzled as to why my hero section file seems to be adopting the styling from the navbar CSS file. I do understand that the index.css file sets properties for the entire app, but in my case, I have separate CSS files for different components instea ...

Display routes in React using the react-router package

Can I use a console command at runtime to display all routes in my application? Despite utilizing react-router, not all routes seem to be functioning properly. In Rails, you can retrieve a list of routes during runtime. ...

Discovering instances of a specific string within a larger string

My goal is to customize the default behavior of the alert function. Below is the code I am using: window.alert=function(txt) { waitOk='wait'; setMsgBox(txt); btnMsgOk.focus(); } However, I need this functionality to vary ba ...

Integrate the complete Mozilla pdf.js viewer into a Vue.js application using webpack through vue-cli

I am trying to integrate the full Mozilla pdf.js viewer into a Vue SPA. After reading a Stack Overflow post with an accepted solution, I still can't seem to get it to work. I keep encountering the 'Uncaught SyntaxError: Unexpected token <&apo ...

"Enhance your PHP/Laravel skills by learning how to insert a new array element into a

I need to find a way to efficiently add a new element to a PHP array. Is there a shortcut to accomplish this without iterating over all the elements? [ "A": ["id": 12, "name": "test1"], "B": ["id&q ...

Guide to seamlessly navigating to an element using a hash in NuxtJS

My aim is to create a smooth scrolling anchor link menu using Nuxt.js, where the user can click on a link and be directed to the corresponding page section. However, I'm facing a dilemma as there are multiple approaches to achieve this functionality, ...

Could you please explain the distinctions among onLoad, onDomready, No wrap - in <head>, and No wrap - in <body>?

When it comes to editing my code, I rely on JSFiddle. However, I have noticed that in certain instances when running JavaScript or jQuery, the code only works if I choose "No wrap - <head>" or "No wrap - <body>". CLICK HERE FOR THE JSFIDDLE EX ...

Adjusting Laravel model, post data retrieval

I am seeking a method where the modifications are automatically performed when I call the object, without altering the actual object itself. Within a controller, the following code is present: $candidate = Candidate::where('slug', '=' ...

Ways to increase the field count in PHP seamlessly with the help of JavaScript, jQuery, or AJAX, without the need to

Within my Yii form, there is a text field labeled certificate_name. I am looking to create a functionality where clicking on the plus icon will increment the text field by one and display it below the previous field. Below is the PHP code snippet I am usi ...

What is the correct way to utilize "data:" in a jQuery AJAX call?

There seems to be an issue with my code within the deletePost function. The problem lies in the fact that $_GET['title'] is empty. Although I set the title value in the ajax using postTitle: $(this).siblings("h3.blog").text(), it doesn't see ...