为什么在使用 module.exports 时会出现 "not a function" 错误?

Why "not a function" error when using module.exports?

如果我有这个递归函数

function checkNested(obj, level, ...rest) {
  if (obj === undefined) return false;
  if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
  return checkNested(obj[level], ...rest);
}

当我尝试将它变成一个模块时,出现了这个错误

checkNested is not a 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);
};

module.exports.checkNested = checkNested;

您需要先定义module.exports,然后才能赋值给它。

所以,这些工作:

module.exports = {}
module.exports.checkNested = checkNested

module.exports = function checkNested(...) {...}

保持简单并像这样使用它:

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);
}

然后像这样导入:

import {checkNested} from "./CheckNeste.js";

如果您在定义函数时将其导出,则无法在模块的其余部分中将其作为函数调用。

这行不通:

module.exports.testFunction = function () { 
  console.log('testFunction')
}

module.exports.mainFunction = function () {
  testFunction() // will throw when importer calls main()
}

如果您希望能够在同一个模块中的其他地方调用它,则必须将 testFunction 与导出它分开定义。

或者,您可以通过 module.exports 引用该函数,但这似乎是个坏主意,因为它将调用者与该函数当前为 public.

的事实联系起来
module.exports.testFunction = function () { 
  console.log('testFunction')
}

module.exports.mainFunction = function () {
  module.exports.testFunction() // works but icky
}

我认为尾递归是问题所在,但老实说我不确定为什么。这是一个简单的 运行nable 演示,它遵循 OP 的模式,应该 工作,但以完全相同的方式失败:

function countLogger( count ) {
    if( count === 0 ) return
    
    console.log(`count ${count}`)
    return countLogger(count - 1)
}

module.exports.countLogger = countLogger

它使用 function 关键字定义了与 export 分开的函数。 (就像 OP,就像我认为完成这项工作所必需的那样。)

它将函数导出为命名导出而不是默认导出。

错误显示:“未捕获的类型错误:countLogger 不是函数”

这与我在第一个示例中得到的错误有重要的不同,后者 (1) 运行 在失败之前出现一次,并且 (2) 表示函数未定义,(3) 给出了电话号码。相比之下,这个版本连运行一次都没有,也没有说这个函数是未定义的,而是说它不是一个函数。

很奇怪。

我可以用这两个文件重现你的问题。

index.js

const checkNested = require('./check-nested');

console.log(checkNested({}, 0));

检查-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;

这里的问题是 check-nested.js 导出一个包含函数的对象。您不能调用导出的对象。您必须调用该包含的函数。一种常见的方法是解构对象:

index.js

const { checkNested } = require('./check-nested');

console.log(checkNested({}, 0));

检查-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;

或使用对象的属性:

index.js

const checkNested = require('./check-nested');

console.log(checkNested.checkNested({}, 0));

检查-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;

或者只导出没有包装器对象的函数

index.js

const checkNested = require('./check-nested');

console.log(checkNested({}, 0));

检查-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;

我更喜欢第一种方法,据我所知这是最常见的方法。