【问题标题】:Call a "local" function within module.exports from another function in module.exports?从 module.exports 中的另一个函数调用 module.exports 中的“本地”函数?
【发布时间】:2012-05-14 18:55:45
【问题描述】:

如何在 module.exports 声明中从另一个函数中调用一个函数?

应用程序.js
var bla = require('./bla.js');
console.log(bla.bar());
bla.js
module.exports = {

  foo: function (req, res, next) {
    return ('foo');
  },

  bar: function(req, res, next) {
    this.foo();
  }

}

我正在尝试从函数 bar 中访问函数 foo,结果如下:

TypeError: Object # has no method 'foo'

如果我将 this.foo() 更改为 foo(),我会得到:

ReferenceError: foo 未定义

【问题讨论】:

  • 我测试了你的代码并且没有错误。 bar 函数返回 undefined 因为没有返回语句。你确定你的测试正确吗?
  • 在节点版本v8.12.0 中测试,不再抛出错误。 bar 没有返回语句,所以运行 console.log(bla.bar()) 只会返回 undefined
  • @Ferchi 谢谢,我错过了同样简单的事情。

标签: node.js express


【解决方案1】:

this.foo() 更改为module.exports.foo()

【讨论】:

  • @NamNguyen 调用exports.foo() 似乎有点尴尬且难以阅读。
  • 我认为这比公认的答案要好。如果您在导出范围之外定义函数,它会增加一个额外的间接级别,虽然有时它可能是可取的,但它会使重构变得更加复杂,例如重命名函数,查找函数的用法等
  • 直接回答问题
  • module.exports.foo()exports.foo() 不适用于 Node.js v5.8.0。
  • exports.foo() 不起作用,但 module.exports.foo() 正在使用 NodeJS v6.9.1
【解决方案2】:

您可以在 module.exports 块之外声明您的函数。

var foo = function (req, res, next) {
  return ('foo');
}

var bar = function (req, res, next) {
  return foo();
}

然后:

module.exports = {
  foo: foo,
  bar: bar
}

【讨论】:

  • 如果我想从方法中访问对象的属性怎么办?
  • 我收到 TypeError: yourClass.youMethod is not a function when I do this。我正在使用节点版本 6.9.1。你必须有退货声明吗?我没有返回语句,因为我的所有代码在函数中都是异步的。
  • 不同风格的漂亮对比 -- gist.github.com/kimmobrunfeldt/10848413
  • 非常好的实现! +1
  • 或者,更简洁地使用 ES6,module.exports = { foo, bar, }
【解决方案3】:

您还可以在 (module.)exports.somemodule 定义之外保存对模块全局范围的引用:

var _this = this;

exports.somefunction = function() {
   console.log('hello');
}

exports.someotherfunction = function() {
   _this.somefunction();
}

【讨论】:

  • 这是更清洁的解决方案!
  • 不需要 _this,你可以在需要的地方直接使用它
  • 直接使用this,无需声明_this
  • 一旦this 不再是正确的this,该建议很有用。 (承诺和回调)
  • 我最喜欢这个解决方案,因为它还提供了一个在 NodeJS 模块中作用域的示例。
【解决方案4】:

另一个选项,更接近 OP 的原始样式,是将要导出的对象放入变量中并引用该变量以调用对象中的其他方法。然后,您可以导出该变量,一切顺利。

var self = {
  foo: function (req, res, next) {
    return ('foo');
  },
  bar: function (req, res, next) {
    return self.foo();
  }
};
module.exports = self;

【讨论】:

    【解决方案5】:

    您也可以这样做以使其更简洁易读。这是我在几个编写良好的开源模块中看到的:

    var self = module.exports = {
    
      foo: function (req, res, next) {
        return ('foo');
      },
    
      bar: function(req, res, next) {
        self.foo();
      }
    
    }
    

    【讨论】:

    • 此 Node.js 版本是否特定?我正在用 v5.8.0 尝试这个,它正在记录未定义。
    • @doublejosh... 你读过这个问题了吗?它询问您如何从另一个调用一个导出的函数。它与访问限制无关
    • 是的,我读过,请重读。这个答案使 foo() 与模块一起导出,这违背了仅在模块内调用的“本地”函数的观点。
    【解决方案6】:

    Node.js 版本 13 开始,您可以利用 ES6 Modules

    export function foo() {
        return 'foo';
    }
    
    export function bar() {
        return foo();
    }
    

    遵循类方法:

    class MyClass {
    
        foo() {
            return 'foo';
        }
    
        bar() {
            return this.foo();
        }
    }
    
    module.exports = new MyClass();
    

    由于 Node 的模块缓存,这只会将类实例化一次:
    https://nodejs.org/api/modules.html#modules_caching

    【讨论】:

    • 如何使用这种方法调用静态方法?
    • @CodeofGod 就像调用任何其他静态方法一样调用它。在这种情况下,如果 foo 是静态的,您可以从 bar 内部调用它,如下所示:MyClass.foo()
    • 是的,我明白了,但是您如何从正在导入它的控制器调用它... const oAccounts = require("...");
    • 您可以导出实际的类,而不是类的实例。这样你就可以使用它的静态方法。但是,如果您随后需要使用其实例方法,则必须在控制器中实例化该类。
    【解决方案7】:
    const Service = {
      foo: (a, b) => a + b,
      bar: (a, b) => Service.foo(a, b) * b
    }
    
    module.exports = Service
    

    【讨论】:

    • 这特别有用,因为您的代码调用Service.foo(),而您的客户端代码也将以相同的命名调用Service.foo()
    • 这是一个完美的答案!
    【解决方案8】:

    为了解决您的问题,我对 bla.js 进行了一些更改,它正在工作,

    var foo= function (req, res, next) {
      console.log('inside foo');
      return ("foo");
    }
    
    var  bar= function(req, res, next) {
      this.foo();
    }
    module.exports = {bar,foo};
    

    app.js 中没有修改

    var bla = require('./bla.js');
    console.log(bla.bar());
    

    【讨论】:

    • 在函数栏中,this.foo()不起作用……它必须是foo()
    【解决方案9】:

    我要做的是创建一个独立的foo 函数并在两个地方引用它。

    这样,它可以防止 this 出现任何问题,无论使用箭头还是常规函数

    function foo(req,res,next) {
      return ('foo');
    }
    

    然后我可以在两个地方引用foo

    module.exports = {
    
      foo, // ES6 for foo:foo
    
      bar: function(req, res, next) {
        foo();
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多