If I have this recursive function
function checkNested(obj, level, ...rest) {
if (obj === undefined) return false;
if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
return checkNested(obj[level], ...rest);
}
When I try to make it a module, I get this error
checkNested is not a function
Can anyone see what I am doing wrong?
function checkNested(obj, level, ...rest) {
if (obj === undefined) return false;
if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
return checkNested(obj[level], ...rest);
};
module.exports.checkNested = checkNested;
CodePudding user response:
I can reproduce your problem with this two files.
index.js
const checkNested = require('./check-nested');
console.log(checkNested({}, 0));
check-nested.js
function checkNested(obj, level, ...rest) {
if (obj === undefined) return false;
if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
return checkNested(obj[level], ...rest);
}
module.exports.checkNested = checkNested;
The problem here is that check-nested.js
exports an object containing a function. You can't call the exported object. You have to call that contained function. One common way is to destructure the object:
index.js
const { checkNested } = require('./check-nested');
console.log(checkNested({}, 0));
check-nested.js
function checkNested(obj, level, ...rest) {
if (obj === undefined) return false;
if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
return checkNested(obj[level], ...rest);
}
module.exports.checkNested = checkNested;
or to use the property of the object:
index.js
const checkNested = require('./check-nested');
console.log(checkNested.checkNested({}, 0));
check-nested.js
function checkNested(obj, level, ...rest) {
if (obj === undefined) return false;
if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
return checkNested(obj[level], ...rest);
}
module.exports.checkNested = checkNested;
or to only export the function without wrapper object
index.js
const checkNested = require('./check-nested');
console.log(checkNested({}, 0));
check-nested.js
function checkNested(obj, level, ...rest) {
if (obj === undefined) return false;
if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
return checkNested(obj[level], ...rest);
}
module.exports = checkNested;
I prefer the first approach and AFAIK it's the most common way.
CodePudding user response:
If you export your function while defining it, it's not available to call as a function within the rest of the module.
This will not work:
module.exports.testFunction = function () {
console.log('testFunction')
}
module.exports.mainFunction = function () {
testFunction() // will throw when importer calls main()
}
You must define testFunction separate from exporting it if you want to be able to call it elsewhere within this same module.
Alternatively, you can reference the function through module.exports, but that seems like a bad idea because it ties callers to the fact that this function is currently public.
module.exports.testFunction = function () {
console.log('testFunction')
}
module.exports.mainFunction = function () {
module.exports.testFunction() // works but icky
}
I think the tail recursion is the problem, but I'm honestly not sure why. Here is a simple runnable demo that follows OP's pattern, and which should work, but fails in precisely the same way:
function countLogger( count ) {
if( count === 0 ) return
console.log(`count ${count}`)
return countLogger(count - 1)
}
module.exports.countLogger = countLogger
It defines the function separate from export, using the function
keyword. (Just like OP, and just like I think is necessary to make this work.)
It exports the function as a named export rather than the default.
The error reads: "Uncaught TypeError: countLogger is not a function"
This is importantly different than the error I get in my first example, which (1) runs once before failing, and (2) says the function isn't defined, (3) gives a line number. By contrast, this version doesn't even run once, and it doesn't say the function is undefined, it says it's not a function.
Very strange.
CodePudding user response:
You need to define module.exports
before you can assign into it.
So, these work:
module.exports = {}
module.exports.checkNested = checkNested
OR
module.exports = function checkNested(...) {...}
CodePudding user response:
Just keep it simple and use it like this:
export function checkNested(obj, level, ...rest) {
if (obj === undefined) return false;
if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
return checkNested(obj[level], ...rest);
}
And import like this:
import {checkNested} from "./CheckNeste.js";