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

Posted

技术标签:

【中文标题】Node.js - 使用 module.exports 作为构造函数【英文标题】:Node.js - use of module.exports as a constructor 【发布时间】:2013-12-30 08:16:28 【问题描述】:

根据 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());

【问题讨论】:

您的示例是语法错误。将 square 重命名为 Square 后,new square() 不再存在。 抱歉,打错了。修复。我的意图是显示以大写开头的对象/函数名称和以小写开头的实例名称。 我想了这么多,这就是我写my answer的原因。我只是想说,我真的很高兴其他人以同样的方式看待模块。我经常使用 new 关键字并组织我的模块以导出单个构造函数。我发现它使解决方案的可读性和概念化更容易。我一眼就能看出我打算使用什么样的构造。像我一样思考的荣誉;) 【参考方案1】:

这个问题与require() 的工作原理没有任何关系。基本上,无论您在模块中设置的 module.exports 是什么,都将从对它的 require() 调用返回。

这相当于:

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

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

有关new 的更复杂的论点,请查看:Is javascript's "new" keyword considered harmful?

【讨论】:

使用 new 关键字没有任何问题。我讨厌它周围的所有 FUD。 @Sukima 同意。 :-D 我指出了为什么在这种情况下无关紧要,并链接到关于new 的另一个问题,以便其他人可以在那里参与战争。【参考方案2】:

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 模块中看不到任何这些,因为整个系统会为您处理所有您需要知道的是有一个具有导出属性的模块对象和一个指向与 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"

【讨论】:

我可以简称为 require('./my-object.js')("foobar") 吗?或者 require('module')(params) 语法是否适用于不同的用例? 没有什么能阻止你,这只是 JavaScript。所以是的,你可以使用更短的语法。 如何定义模块的伪代码示例,让我对Node.js模块系统的理解彻底清晰。谢谢!【参考方案3】:

在我看来,一些 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 关键字来实例化它。其他一切都保持不变。

【讨论】:

结构异常简洁! 因此,在您的 new 和不使用它似乎没有区别。但是,这仅仅是因为您对this instanceof square 进行了检查吗?如果是这样,该机制到底在做什么? 我遇到并查找的问题,以防对其他人有帮助:importexport 定义在哪里? 这些是 ECMAScript 6 (ES6) 中的保留关键字.在 ES6 之前,必须使用库来管理模块。 Node 的模块化是根据 CommonJS 库的 Modules 建模的。 export default Square 中的default 是什么? 这指定了当您只导入“文件”而不是从该文件中导入其他特定导出时要导入的内容。只要它们存在,我就发现这些页面很有帮助:spring.io/understanding/javascript-modules 和 exploringjs.com/es6/ch_modules.html【参考方案4】:

示例代码为:

在主要

square(width,function (data)

   console.log(data.squareVal);
);

使用以下方法可能有效

exports.square = function(width,callback)

     var aa = new Object();
     callback(aa.squareVal = width * width);    

【讨论】:

【参考方案5】:

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

这种方式实际上是在创建一个新函数,例如我们在 Web 浏览器环境中使用 JS 创建的。

我个人更喜欢原型方法,正如 Sukima 在这篇文章中所建议的那样:Node.js - use of module.exports as a constructor

【讨论】:

以上是关于Node.js - 使用 module.exports 作为构造函数的主要内容,如果未能解决你的问题,请参考以下文章

webpack的loader

nginx反向代理应用实例

nginx反向代理应用实例

Typescript 检查导出的接口

续集 findOrCreate 插入新行但返回未定义主键的对象

vue.config.js 似乎没有加载