I am trying to get a recursion method to work in a class context. Within 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 when I just used it as function countChildren = ...
) it can't... find (?) itself: Cannot read property 'countChildren' of undefined
at the recursion.
Does anyone have any ideas?
However, while JavaScript's functional coding style does support recursive functions, we need to be aware that most JavaScript compilers are not currently optimized to support them safely. Recursion is best applied when you need to call the same function repeatedly with different parameters from within a loop.
A function can refer to and call itself.
Iteration can be used to repeatedly execute a set of statements without the overhead of function calls and without using stack memory. Iteration is faster and more efficient than recursion. It's easier to optimize iterative codes, and they generally have polynomial time complexity.
Basically there are two ways to code recursive functions in TypeScript: First by directly calling the function from within itself and. Second by using an indirect call.
The problem arises because within your loop, this
gets redefined to the inner function scope.
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;
}
Try binding the method in the constructor.
Also, by using an arrow function for your 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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With