Javascript recursion in class

I am trying to get a recursion method to work in the context of a class. In my class, I have the following method:

    countChildren(n, levelWidth, level) {
    if (n.children && n.children.length > 0) {
        if (levelWidth.length <= level + 1) {
            levelWidth.push(0);
        }
        levelWidth[level + 1] += n.children.length;
        n.children.forEach(function (n) {
            this.countChildren(n, levelWidth, level+1);
        });    
    }
    // Return largest openend width
    return levelWidth;
}

      

However, when I use this method (which worked before I used it like function countChildren = ...

), it cannot ... find (?) Itself: Cannot read property 'countChildren' of undefined

in recursion.

Does anyone have any ideas?

+3


source to share


4 answers


The problem comes from being this

overridden in your loop to the scope of the inner function.



countChildren(n, levelWidth, level) {
    var self = this; // Get a reference to your object.

    if (n.children && n.children.length > 0) {
        if (levelWidth.length <= level + 1) {
            levelWidth.push(0);
        }
        levelWidth[level + 1] += n.children.length;

        n.children.forEach(function (n) {
            // Use "self" instead of "this" to avoid the change in scope.
            self.countChildren(n, levelWidth, level+1);
        });    
    }
    // Return largest openend width
    return levelWidth;
}

      

+5


source


Try to bind the method in the constructor.
Also, by using the arrow function for yours forEach

, you keep the scope of the class this

.



export class MyClass {
    constructor(){
        this.countChildren = this.countChildren.bind(this);
    }

    countChildren(n, levelWidth, level){ ... }


    countChildren(n, levelWidth, level) {
        if (n.children && n.children.length > 0) {
            if (levelWidth.length <= level + 1) {
                levelWidth.push(0);
            }
            levelWidth[level + 1] += n.children.length;
            n.children.forEach( n => { // arrow function do not need to rebind this
                this.countChildren(n, levelWidth, level+1);
            });    
        }
        // Return largest openend width
        return levelWidth;
    }
}

      

+4


source


It is inside foreach than it is in class. In your case, this means the current element is being repeated.

you need to bind the scope.

n.children.forEach(function (n) {
   this.countChildren(n, levelWidth, level+1);
}.bind(this));   

      

0


source


Try using .call()

to call a function. This way you can specify the context directly.

Like this:

this.countChildren.call(this, n, levelWid);

th, level + 1

Edit: Seeing my mistake, you should actually bind the anonymous function:

like this:

  n.children.forEach(function (n) {
    this.countChildren(n, levelWidth, level+1);
  }.bind(this)); 

      

-1


source







All Articles