Issues with recursion involving "undefined return" in JavaScript

I'm struggling with recursion. Despite reading similar questions, I haven't found a solution yet. My function works perfectly internally but returns "undefined" in the end.

Currently, I'm dealing with a binary tree and attempting to create a function that can determine if any nodes on a certain level have children.

class tree_node {
    constructor(n_array, parent) {
        this.n_array = n_array;
        this.has_children = false;
        this.children = [];
        if (parent != null) {
            this.parent = parent;
            this.level = this.parent.level + 1;
        }
        else {
            this.level = 0;
        }
        // executing the tree
        this.child();
    }
    child() {
        if (this.n_array.length != 1) {
            this.has_children = true;
            let m = Math.floor(this.n_array.length / 2);
            let l = this.n_array.slice(0, m);
            let r = this.n_array.slice(m);
            const left = new tree_node(l, this);
            const right = new tree_node(r, this);
            this.children.push(left, right);
        }
        else return 0
    }

    get_if_node_has_children(node, level) {
        console.log(node.level, node.has_children)
        if (node.has_children && node.level < level) {
            console.log("inside loop")
            node.children.forEach(element => {
                return element.get_if_node_has_children(element, level);
            });
        }
        else {
            console.log("first else")
            if (node.level == level && node.has_children) {
                console.log("node.level == level && node.has_children " + node.n_array)
                return true;
            }
            else {
                console.log("return false")
                return false;
            }
        }
    }
    show() {
        console.log(this.n_array + " | Level: " + this.level + ". Has children = " + this.has_children);
        if (this.has_children) {
            this.children.forEach(element => {
                return element.show();
            });
        }
        else {
            return 0;
        }
    }    
}

get_if_node_has_children(node, level)
seems to be functioning correctly internally as per my expectations and logs. However, it strangely returns "undefined." I need help figuring out where I went wrong.

let root = [];

class tree_node {
  constructor(n_array, parent) {
    this.n_array = n_array;
    this.has_children = false;
    this.children = [];
    // upon creating an instance of the class, parent is usually null
    if (parent != null) {
      this.parent = parent;
      this.level = this.parent.level + 1;
    } else {
      this.level = 0;
    }
    // executing the tree
    this.child();
  }
  child() {
    if (this.n_array.length != 1) {
      this.has_children = true;
      let m = Math.floor(this.n_array.length / 2);
      let l = this.n_array.slice(0, m);
      let r = this.n_array.slice(m);
      const left = new tree_node(l, this);
      const right = new tree_node(r, this);
      this.children.push(left, right);
    } else return 0
  }

  get_if_node_has_children(node, level) {
    console.log(node.level, node.has_children)

    if (node.has_children && node.level < level) {
      console.log("in loop")
      node.children.forEach(element => {
        return element.get_if_node_has_children(element, level);
      });
    } else {
      console.log("first else")
      if (node.level == level && node.has_children) {
        console.log("node.level == level && node.has_children " + node.n_array)
        return true;
      } else {
        console.log("return false")
        return false;
      }
    }
  }

  show() {
    console.log(this.n_array + " | Level: " + this.level + ". Has children = " + this.has_children);
    if (this.has_children) {
      this.children.forEach(element => {
        return element.show();
      });
    } else {
      return 0;
    }
  }
  // CLASS END ===========================
}

root = new tree_node([1, 3, 5, 7, 9, ])
console.log("=== root.show() ===")
root.show();
console.log("=== let a = root.get_if_node_has_children(root, 2) ===")
let a = root.get_if_node_has_children(root, 2)
console.log(" a is " + a)

Answer №1

Here are a couple of issues to address:

  1. The return statement inside a callback (such as the forEach callback) will only exit the callback function, not the main function that called forEach. It's advisable to use for-of in modern code unless you specifically require the index of each element.

  2. You should check the result of the recursive call before returning it. If the first child node that is called returns false, you need to continue searching instead of immediately returning false.

To fix these issues, consider this revised code snippet:

get_if_node_has_children(node, level) {
    if (node.has_children && node.level < level) {
        for (const element of node.children) { 
            const hasChild = element.get_if_node_has_children(element, level);
            if (hasChild) {     
                return true;    
            }                   
        }
        return false; 
    } else {
        if (node.level === level && node.has_children) {
            return true;
        } else {
            return false;
        }
    }
}

A slightly refined version could look like this:

get_if_node_has_children(node, level) {
    if (node.has_children) {
        if (node.level === level) {
            return true;
        }
        if (node.level < level) {
            for (const element of node.children) {
                if (element.get_if_node_has_children(element, level)) {
                    return true;
                }
            }
        }
    }
    return false;
}

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

Is the Angular-fullstack generator production application experiencing issues with serving socket.io correctly?

Having a bit of trouble with two angular-fullstack apps deployed on AWS using the same setup and configuration. It appears that socket.io-client/socket.io.js is not being properly served on one of them, despite both apps having identical settings. There ...

Is it possible to trigger a function using an event on "Any specified selector within a provided array"?

Trying to figure out how to show/hide a group of divs with different IDs by executing a function after creating an array of IDs for the NavBar. I'm having trouble getting started, but here's what I was thinking: $.each(array1, function(i, value) ...

Is it possible to rearrange the node_modules directory?

Within the node_modules directory, there exists a large and extensive collection of modules. These modules are often duplicated in various sub-folders throughout the directory, with some containing identical versions while others differ by minor versions. ...

Tips to avoid the page from scrolling to the top when the menu is opened

Whenever a user taps the menu button on the page, a full-page menu opens. However, there is an issue - the main content page automatically scrolls to the top. Can you provide suggestions on how to prevent this from happening? I have already looked into a s ...

Components rendered by v-for are failing to display on the production server, however, they are

Struggling to dynamically generate bootstrap tabs (b-tabs) using vue's v-for. Everything functions perfectly on my local server, but once pushed to production, the tabs fail to render. After utilizing the vue chrome debugger to verify that my backend ...

Combine two collections into a single collection in MongoDB using JavaScript

I have been attempting to merge two collections into a new collection while inserting the resulting data into the new collection. Here is the code I am using for the merge: db.users.aggregate( [{ $lookup: { from: "posts", localField: "_ ...

Challenges with using the $.remove() function in jQuery

In simple terms... I am dealing with an element called clone. It's a div with various other tags nested within it. There is also a .x contained within it. My goal is to remove the .x and then append this modified element to another element. Unfortu ...

Unable to establish a connection to the server while handling a jQuery Ajax error

I'm in the process of pinpointing an issue that occurs when submitting an Ajax request through jQuery and encountering a failed connection to the server. The scenario involves loading a page from the server, then deliberately disconnecting the network ...

Issue with Calendar Control not loading in Internet Explorer 9 when using ASP

I have been trying to incorporate a calendar control in my code that selects a date and returns it to a text field. It worked perfectly fine on browsers prior to IE 8, but I'm facing issues with IE 9. Can someone help me troubleshoot this problem and ...

What is the best way to update an element in an array inside a JavaScript object

In my NodeJS code, I have an object structured like this: const jsonData= { "description": "description", "hosts": [ "host1", "host2", "host3" ] } The task at ...

Why does my computed property become undefined during unit testing of a head() method in Vue.js with Nuxt.js?

In my Vue.js + Nuxt.js component, I have implemented a head() method: <script> export default { name: 'my-page', head() { return { title: `${this.currentPage}` }; }, ... } </script> ...

Convert an array of objects into an array of objects with combined values

Here is an example of an array containing objects: array = [ {prop1: 'teste1', prop2: 'value1', prop3: 'anotherValue1' }, {prop1: 'teste2', prop2: 'value2', prop3: 'anotherValue2' }, {prop1: &apo ...

Verify if an Ajax request has been made

I've been trying to figure out how to determine if a request is made via AJAX in C#, but I'm having trouble getting it to work. Below is the code I'm using. I am using a method to make an AJAX call on the client side (I'm using the Acti ...

Create a dropdown menu with selectable options using a b-form-select

I am working with a b-form-select element that displays options based on user input. I am trying to figure out how to trigger a function when the user selects one of the dynamically generated <b-form-option> elements, but I am struggling to capture b ...

Style the date using moment

All languages had a question like this except for JavaScript. I am trying to determine, based on the variable "day," whether it represents today, tomorrow, or any other day. ...

populate form fields with database data using ajax

I'm currently working on populating form fields with data from a database using ajax and jQuery in my Codeigniter project. I have been able to retrieve and alert the database values into an array, which you can see in this image: alert of the data arr ...

Coloring table rows based on results

Recently, I started working with AngularJs and encountered an issue while trying to manipulate JSON data in a specific format: [ { 'StudentName':'abc', 'maths':'0', 'english':'0', ...

"Successfully rendering the map on the initial load, but encountering an error of 'cannot map undefined'

Having trouble displaying data retrieved from an API. Initially, the movie titles are shown without any issues. However, upon refreshing the page, an error message stating "cannot map undefined" appears. Here is the code snippet: const [media, set ...

Utilize the jQuery autocomplete UI Widget to trigger a select event on a dynamically generated row in a table

Currently, I have successfully implemented a jQuery autocomplete feature on the text input of a table data element called txtRow1. The data for this autocomplete is fetched remotely from a MySQL database and returned in JSON format as 'value' for ...

What is the best way to change the response URL in an AJAX function?

I have a function using ajax that redirects to the response from a specified URL upon success: document.getElementById("button1").addEventListener("click", function (e) { e.preventDefault(); $.ajax({ url: 'http://localhost:8080/someLo ...