Node.js-使用module.exports作为构造函数


120

根据Node.js手册:

如果您希望模块导出的根是一个函数(例如构造函数),或者想一次导出一个完整的对象而不是一次构建一个对象,则将其分配给module.exports而不是export 。

给出的示例是:

// file: square.js
module.exports = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

并像这样使用:

var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());

我的问题:为什么示例不使用正方形作为对象?以下内容是否有效,是否会使示例更加“面向对象”?

var Square = require('./square.js');
var mySquare = new Square(2);
console.log('The area of my square is ' + mySquare.area());

1
您的示例是语法错误。重命名后squareSquarenew square()不再存在。
Sukima 2013年

3
对不起,那是一个错字。解决它。我的意图是显示对象/函数名称以大写字母开头,实例名称以小写字母开头。
Naresh 2013年

4
我想了很多,这就是为什么我写答案的原因。我只是想说,我真的很高兴其他人以同样的方式看模块。我经常使用new关键字并组织模块以导出单个构造函数。我发现它使解决方案的可读性和概念化更加容易。我一眼就能知道我打算使用哪种构造。像我一样思考的荣誉;)
Sukima 2013年

Answers:


173

CommonJS模块允许两种方法来定义导出的属性。无论哪种情况,您都将返回对象/功能。因为函数是JavaScript中的一等公民,所以它们可以像对象一样操作(从技术上讲,它们是对象)。就是说,您有关使用new关键字的问题有一个简单的答案:是的。我会说明...

模块出口

您可以使用exports提供的变量将属性附加到该变量。一旦在另一个模块中需要,这些分配属性将变为可用。或者,您可以将一个对象分配给module.exports属性。无论哪种情况,所返回的require()都是对的值的引用module.exports

有关如何定义模块的伪代码示例:

var theModule = {
  exports: {}
};

(function(module, exports, require) {

  // Your module code goes here

})(theModule, theModule.exports, theRequireFunction);

在上面的示例中,module.exportsexports是相同的对象。最酷的部分是,您不会在CommonJS模块中看到任何内容,因为整个系统都会为您提供帮助,因此您所需要知道的是,有一个带有exports属性和指向变量的export变量的模块对象module.exports也做同样的事情。

需要构造函数

因为您可以直接将函数附加到函数上module.exports,所以基本上可以返回一个函数,并且像其他任何函数一样,都可以将其作为构造函数进行管理(这用斜体表示,因为JavaScript中的函数和构造函数之间的唯一区别是您打算如何使用它。没有区别。)

因此,以下代码非常好,我个人鼓励这样做:

// My module
function MyObject(bar) {
  this.bar = bar;
}

MyObject.prototype.foo = function foo() {
  console.log(this.bar);
};

module.exports = MyObject;

// In another module:
var MyObjectOrSomeCleverName = require("./my_object.js");
var my_obj_instance = new MyObjectOrSomeCleverName("foobar");
my_obj_instance.foo(); // => "foobar"

要求非建设者

对于类似非构造函数的函数也是如此:

// My Module
exports.someFunction = function someFunction(msg) {
  console.log(msg);
}

// In another module
var MyModule = require("./my_module.js");
MyModule.someFunction("foobar"); // => "foobar"

2
我可以简称为require('./ my-object.js')(“ foobar”)吗?还是针对不同用例的require('module')(params)语法?
汉普斯·阿赫格伦2014年

1
没什么能阻止您的,全都是JavaScript。所以可以,您可以使用较短的语法。
Sukima 2014年

3
关于如何定义模块的伪代码示例完全清除了我对Node.js模块系统的理解。谢谢!
Nitax

130

我认为,有些node.js示例是非常人为设计的。

您可能希望在现实世界中看到更多类似的东西

// square.js
function Square(width) {

  if (!(this instanceof Square)) {
    return new Square(width);
  }

  this.width = width;
};

Square.prototype.area = function area() {
  return Math.pow(this.width, 2);
};

module.exports = Square;

用法

var Square = require("./square");

// you can use `new` keyword
var s = new Square(5);
s.area(); // 25

// or you can skip it!
var s2 = Square(10);
s2.area(); // 100

对于ES6人员

class Square {
  constructor(width) {
    this.width = width;
  }
  area() {
    return Math.pow(this.width, 2);
  }
}

export default Square;

在ES6中使用它

import Square from "./square";
// ...

使用类时,必须使用new关键字将其实例化。其他一切保持不变。


3
结构异常简洁!
Christophe Marois,2014年

1
因此,在您的<ES6示例中,似乎使用new和不使用它之间没有区别。但是,那仅仅是因为您有要检查的东西this instanceof square吗?如果是这样,该机制到底在做什么?
理查兹(Arichards)

1
我的问题了,抬起头来,在情况下,它是帮助他人:在哪里importexport界定?这些是ECMAScript 6(ES6)中的保留关键字。在ES6之前,必须使用库来管理模块。节点的调制以CommonJS库的模块为模型。什么是defaultexport default Square这指定当您仅导入“文件”而不是从该文件进行其他特定导出时要导入的内容。只要他们存在,我发现这些页面有所帮助:spring.io/understanding/javascript-modulesexploringjs.com/es6/ch_modules.html
arichards

1

这个问题实际上与require()工作方式没有任何关系。基本上,您module.exports在模块中设置的任何内容都会从对其的require()调用中返回。

这等效于:

var square = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

new呼叫时不需要关键字square。您不是从返回函数实例本身square,而是在最后返回一个新对象。因此,您可以直接直接调用此函数。

有关周围更复杂的参数new,请查看以下内容: JavaScript的“ new”关键字是否被认为有害?


3
使用new关键字没有任何问题。我讨厌周围的所有FUD。
Sukima 2013年

1
@Sukima同意。:-D我要指出的是在这种情况下为什么没有关系,并与其他问题联系在一起,new以便其他人可以在那里参加战争。
布拉德

0

示例代码为:

在主要

square(width,function (data)
{
   console.log(data.squareVal);
});

使用以下内容可能有效

exports.square = function(width,callback)
{
     var aa = new Object();
     callback(aa.squareVal = width * width);    
}

0

最后,Node是关于Javascript的。JS有几种方法可以完成某件事,获得“构造函数”是同一件事,重要的是返回一个函数

实际上,通过这种方式您可以创建一个新功能,例如我们在Web浏览器环境中使用JS创建的功能。

我个人更喜欢原型方法,如Sukima在这篇文章中建议的:Node.js-使用module.exports作为构造函数

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.