【问题标题】:Why "not a function" error when using module.exports?为什么在使用 module.exports 时出现“不是函数”错误?
【发布时间】:2021-10-07 14:21:48
【问题描述】:

如果我有这个递归函数

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;

【问题讨论】:

  • 你在哪里以及如何称呼它?
  • @Bergi 我有一个server.js 那个const checkNested = require('./functions/checkNested');。如果这就是你的意思?
  • 而 checkNested 是这个文件吗?
  • @SandraSchlichting 好吧,checkNested 是模块导出对象,而不是函数,如果你这样导入的话。尝试记录它,您会发现问题所在。
  • 你要么想要const {checkNested} = require('./functions/checkNested'); 要么 module.exports = checkNested;

标签: javascript node.js ecmascript-6


【解决方案1】:

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

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;

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

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;

或者使用对象的属性:

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;

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

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;

我更喜欢第一种方法,AFAIK 是最常见的方法。

【讨论】:

    【解决方案2】:

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

    这不起作用:

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

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

    或者,您可以通过 module.exports 引用该函数,但这似乎是个坏主意,因为它将调用者与该函数当前是公共的事实联系在一起。

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

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

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

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

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

    错误显示:“Uncaught TypeError: countLogger is not a function”

    这与我在第一个示例中遇到的错误非常不同,该错误 (1) 在失败前运行一次,(2) 表示该函数未定义,(3) 给出了行号。相比之下,这个版本甚至没有运行一次,并且没有说函数是未定义的,而是说它不是函数。

    很奇怪。

    【讨论】:

    • 看起来 OP 没有直接导出函数。问题在于他们如何导入模块/功能。
    • OP 正在递归调用函数。我认为这就是问题所在。
    • 如果函数如示例中所示声明(作为函数声明),则不会。当然,如果他们以某种方式重新分配给checkNested,那将是一个问题,但没有证据证明这一点。
    • 我尝试时失败了。
    • “这是一个遵循 OP 模式的简单可运行演示,它应该可以工作,但以完全相同的方式失败:” 你是如何调用该函数的?跨度>
    【解决方案3】:

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

    所以,这些工作:

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

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

    【讨论】:

    【解决方案4】:

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

    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";
    

    【讨论】:

    • 问题中的代码是Common JS。你的代码是 ES6。如果支持 ES6 但并不总是支持 ES6,此更改可能会解决问题。
    • 这是一个很好的观点,但是标记为 ECMA-6 的人,所以...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多