web-dev-qa-db-fra.com

Node.js - utilisation de module.exports en tant que constructeur

Selon le manuel de Node.js:

Si vous souhaitez que la racine de l'exportation de votre module soit une fonction (telle qu'un constructeur) ou si vous souhaitez exporter un objet complet dans une affectation au lieu de la construire propriété par propriété, affectez-le à module.exports au lieu d'exportations. .

L'exemple donné est:

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

et utilisé comme ceci:

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

Ma question: pourquoi l'exemple n'utilise-t-il pas le carré comme objet? Le texte suivant est-il valide et rend-il l’exemple plus "orienté objet"?

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

Les modules CommonJS permettent deux manières de définir les propriétés exportées. Dans les deux cas, vous retournez un objet/une fonction. Parce que les fonctions sont des citoyens de première classe en JavaScript, elles peuvent agir comme des objets (techniquement, elles sont des objets). Cela dit, votre question sur l'utilisation des mots-clés new a une réponse simple: oui. Je vais illustrer ...

Exportation de modules

Vous pouvez soit utiliser la variable exports fournie pour y attacher des propriétés. Une fois requises dans un autre module, ces propriétés d'assignation deviennent disponibles. Vous pouvez également affecter un objet à la propriété module.exports. Dans les deux cas, ce qui est retourné par require() est une référence à la valeur de module.exports.

Un exemple de pseudo-code de la définition d'un module:

var theModule = {
  exports: {}
};

(function(module, exports, require) {

  // Your module code goes here

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

Dans l'exemple ci-dessus, module.exports et exports sont le même objet. La partie intéressante est que vous ne voyez rien de cela dans vos modules CommonJS car tout le système s’occupe de cela pour vous. Tout ce que vous devez savoir, c’est qu’il existe un objet module avec une propriété exports et une variable exports qui pointe vers le C'est la même chose que module.exports.

Exiger avec des constructeurs

Comme vous pouvez attacher une fonction directement à module.exports, vous pouvez essentiellement renvoyer une fonction et, comme toute fonction, elle pourrait être gérée comme un constructeur (en italique, la seule différence entre une fonction et un constructeur en JavaScript est la façon dont vous avez l’intention de l’utiliser. Techniquement, il n’ya pas de différence.)

Le code suivant est donc parfaitement bon et je l’encourage personnellement:

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

Require pour les non-constructeurs

La même chose vaut pour les fonctions non constructeurs:

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

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

À mon avis, certains exemples de node.js sont assez artificiels.

Vous pourriez vous attendre à voir quelque chose de plus semblable à cela dans le monde réel

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

Usage

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

Pour les personnes ES6

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

export default Square;

Utilisation dans ES6

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

Lorsque vous utilisez une classe, vous devez utiliser le mot clé new pour l'instancier. Tout le reste demeure inchangé.

125
maček

Cette question n'a vraiment rien à voir avec le fonctionnement de require(). Fondamentalement, tout ce que vous définissez module.exports dans votre module sera renvoyé par l'appel require().

Cela équivaudrait à:

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

Le mot clé new n'est pas nécessaire lorsque vous appelez square. Vous ne renvoyez pas l'instance de fonction elle-même de square, vous renvoyez un nouvel objet à la fin. Par conséquent, vous pouvez simplement appeler cette fonction directement.

Pour des arguments plus complexes autour de new, consultez ceci: Le "nouveau" mot clé de JavaScript est-il considéré comme dangereux?

1
Brad

Le code d'exemple est:

en principal

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

en utilisant ce qui suit peut

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

À la fin, Node concerne le Javascript. JS a plusieurs façons d'accomplir quelque chose, c'est la même chose pour obtenir un "constructeur", L'important est de retourner une fonction .

De cette façon, vous créez en fait une nouvelle fonction, comme nous avons créé en utilisant l'environnement JS sur un navigateur Web, par exemple.

Personnellement, je préfère l'approche prototype, comme Sukima l'a suggéré dans ce message: Node.js - utilisation de module.exports en tant que constructeur

0
Josue