【问题标题】:Node module.exports returns undefined节点 module.exports 返回未定义
【发布时间】:2015-12-29 04:43:24
【问题描述】:

我遇到了 Node.js 和 module.exports 的问题。我知道module.exports 是一个返回对象的调用,该对象具有分配给它的任何属性。

如果我有这样的文件结构:

// formatting.js

function Format(text) {
    this.text = text;
}

module.exports = Format;

用这个:

// index.js

var formatting = require('./formatting');

有没有办法初始化Format 对象并像这样使用它?

formatting('foo');
console.log(formatting.text);

每当我尝试这样做时,都会收到一条错误消息,显示为formatting is not a function。然后我必须这样做:

var x = new formatting('foo');
console.log(x.text);

这看起来很麻烦。

keypressrequest 等模块中,它们可以直接使用,如下所示:

var keypress = require('keypress');

keypress(std.in);

var request = require('request);

request('http://www.google.com', function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body) // Show the HTML for the Google homepage.
  }
})

这是如何工作的?

【问题讨论】:

  • 这行得通吗? varformatting = require('./formatting.js');
  • 在您的代码中,您从格式化模块返回函数构造函数。相反,您希望将其作为对象返回,以便您可以直接使用它。
  • @PardeepDhingra 我该怎么做?
  • @apizzimenti 检查我的答案。

标签: javascript node.js node-modules


【解决方案1】:

我建议将 new 调用包装在它自己的函数中,然后返回:

function Format(text) {
  this.text = text;
}

function formatting(text) {
  return new Format(text);
}

module.exports = formatting;

这样你应该仍然可以做到:

var format = formatting('foo');
console.log(format.text);


编辑

request 的东西而言,您必须记住的一件事是,在 JavaScript 中,函数仍然是对象。这意味着您仍然可以向它们添加属性和方法。这就是他们在request 中所做的事情,尽管总体而言,解释这个答案中的每个细节有点太复杂了。据我所知,他们向request 函数添加了一堆方法(对象上的函数)。这就是为什么您可以立即调用像request(blah, blah).pipe(blah).on(blah) 这样的方法。根据调用request 函数的返回值,您可以将其他一些方法链接到它的后面。当您使用请求时,它不是一个对象,而是一个函数(但从技术上讲仍然是一个对象)。要演示函数如何仍然是对象以及如何向它们添加方法,请查看以下简单示例代码:

function hey(){
  return;
}

hey.sayHello = function(name) {
  console.log('Hello ' + name);
} 

hey.sayHello('John'); //=> Hello John

这基本上就是他们正在做的事情,只是要复杂得多,还有更多的事情要做。

【讨论】:

  • 是的,可以,但是可以通过调用formatting('foo') 而不是var format = formatting('foo') 来初始化对象吗?
  • 什么意思?当您初始化它时,您不想将返回的对象设置为变量吗?是的,我想可以做类似console.log(formatting('foo').text) 这样的事情,但这样做有什么意义呢?
  • 对,我明白了。在您的第二个代码块中,formatting 是对require('./formatting') 的引用,对吗?
  • 是的,如果在顶部有你所有其他的要求你做了var formatting = require('./formatting');,那是我得到formatting() 函数的地方。
  • 另外,如果您对request 的工作原理感到好奇,您应该查看使其运行的代码:github.com/request/request/blob/master/index.js
【解决方案2】:
module.exports = Format;

这将返回 Format 构造函数,而您将返回 require('./formatting')

另一方面,下面的代码会返回一个Format的实例,你可以直接调用它的方法:

module.exports = new Format();

【讨论】:

  • 如果我这样做然后再执行formatting('text') 并且我尝试控制台记录对象的text 属性,它仍然显示formatting is not a function。我做错了什么吗?
  • 是的,因为一旦使用 new 从构造函数中创建对象,它就不再是函数,而是通过将 构造函数 函数应用于新对象而创建的对象.因此,如果您想要一个模块同时是一个对象和一个像 jQuery 这样的函数,那么构造函数模式不是正确的方法。相反,首先导出一个函数,然后将属性附加到它。
  • @lleaff 所以如果我执行第二个选项,然后在 index.js 中运行format('foo'),那么它会将“foo”分配给text 属性? module.exports 正在返回该类的空实例,然后使用 format('foo') 调用其构造函数正确分配属性?
  • @apizzimenti 查看 Sam 的回答我认为这就是你的意思。
【解决方案3】:

试试这个:

模块格式化:

function Format() {
    this.setter = function(text) {
      this.text = text;
    }
    this.show = function() {
      console.log(this.text);
    } 
}
//this says I want to return empty object of Format type created by Format constructor.

module.exports = new Format();

index.js

var formatting = require('./formatting');
formatting('Welcome');
console.log(formatting.show());

【讨论】:

  • 你能说一下module.exports = new Format();的细节吗?
  • 这对你有用吗?它仍然在调用formatting('Welcome') 的那一行返回错误formatting is not a function
  • 由于 fromatting 是格式类的对象,所以我们不能将“文本”传递给对象,我们需要一个 setter 方法。
猜你喜欢
  • 2019-07-14
  • 2017-12-08
  • 1970-01-01
  • 2014-09-23
  • 2020-08-17
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多