I have a function that searches through a tree of folders and finds the selected folder's parent folder.
Here is the function.
getParentFolder: function (searchroot, childFolder) {
searchroot.subfolders.forEach(function (folder) {
if (folder.key == childFolder.key) {
return searchroot;
}
else {
if (folder.subfolders) {
return this.getParentFolder(folder, childFolder);
}
}
});
}
When I call this with this.getParentFolder(rootFolder, childFolder);
It simply just gives me: Uncaught TypeError: this.getParentFolder is not a function Why is this? In the same file I call other functions they work perfectly fine. This is the only function that I fail to be able to call. Is it because of the recursion?
The syntax for recursive function is: function recurse() { // function code recurse(); // function code } recurse(); Here, the recurse() function is a recursive function. It is calling itself inside the function.
Recursion is a programming pattern or concept embedded in many programming languages, and JavaScript is not left out. It is a feature used in creating a function that keeps calling itself but with a smaller input every consecutive time until the code's desired result from the start is achieved.
You have to keep this
in a variable as you change your context inside the forEach
method.
getParentFolder: function(searchroot, childFolder) {
var self = this;
searchroot.subfolders.forEach(function(folder) {
if (folder.key == childFolder.key) {
return searchroot;
} else {
if (folder.subfolders) {
return self.getParentFolder(folder, childFolder);
}
}
});
}
Also, return
statement won't work the way you want. I recommend you to enumerate the array using a for loop :
getParentFolder: function(searchroot, childFolder) {
for (var i = 0; i < searchroot.subfolders.length; i++) {
var folder = searchroot.subfolders[i];
if (folder.key == childFolder.key) {
return searchroot;
} else {
if (folder.subfolders) {
return self.getParentFolder(folder, childFolder);
}
}
}
}
The problem is that your this
is different inside of function you passed into the forEach
. You need to bind the outer this
to the inner function:
getParentFolder: function(searchroot, childFolder) {
searchroot.subfolders.forEach(function(folder) {
if (folder.key == childFolder.key) {
return searchroot;
} else {
if (folder.subfolders) {
return this.getParentFolder(folder, childFolder);
}
}
}, this); // pass in outer this as context for inner function
}
From Array.prototype.forEach()
on MDN:
Syntax:
arr.forEach(function callback(currentValue, index, array) { //your iterator }[, thisArg]);
Alternative Solution using ES6:
As mishu mentioned in the comments, the new ES6 arrow syntax also solves this problem. Your code in ES6 would look something like this:
getParentFolder: function(searchroot, childFolder) {
searchroot.subfolders.forEach((folder) => {
if (folder.key == childFolder.key) {
return searchroot;
} else {
if (folder.subfolders) {
return this.getParentFolder(folder, childFolder);
}
}
});
}
Arrow functions is ES6 do not bind this
(see MDN) so the outer this
can be accessed from within the arrow function.
Note that not all browsers support arrow functions yet (see Browser compatibility on MDN). To support older browsers, you can transpile ES6 to ES5 using Babel.
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