3

いくつかの機能を持つ node.js モジュールを開発しています。
モジュール自体は、開始するためにいくつかの構成を必要とします (デフォルトが存在します...上書きすることができます - ファイルパスなど)

関数をエクスポートする際に推奨されるアプローチは何ですか? require ステートメントからインスタンス化して、構成オブジェクト (オプション) をコンストラクターに渡すことを許可しますか?

var MyModule = require('myModule);

var myModule = new MyModule({
    name: "test name"
});

myModule.doThing(function(x){

});

これをモジュールに入れる:

module.exports = function MyModule(){
        MyModule.prototype.config = {name: "default name"}

            function doThing(cb){
                //do stuff
                cb();
            }
}

または、モジュール内の exports ステートメントからインスタンスを作成し、次のように使用します。

var myModule = require('myModule);

myModule.config = {name: "test name"}

myModule.doThing(function(x){

});

代わりに、これをモジュールに入れます:

module.exports = exports = MyModule();

function MyModule(){
MyModule.prototype.config = {name: "default name"}

    function doThing(cb){
        //do stuff
        cb();
    }
}
4

2 に答える 2

6

インスタンス化するときにユーザーがオブジェクトを提供できるようにし、デフォルトをプロトタイプに入れます。また、構成機能を提供することもできます。これにより、(現在または将来) キー/値を検証し、インスタンス化後にユーザーが構成を設定できるようになります。

// Module

var Mod = module.exports = function Mod (opts) {
  opts = (opts === Object(opts)) ? opts :  {};

  // This allows users to instanciate without the `new` keyword
  if (! (this instanceof Mod)) {
    return new Mod(opts);
  }

  // Copy user provided configs to this.config
  for (var key in opts) if ({}.hasOwnProperty.call(opts, key)) {
    this.config[key] = opts[key];
  }
};

Mod.prototype.config = {
  foo : 'foo',
  bar : 'bar'
};

Mod.prototype.configure = function configure (key, val) {
  this.config[key] = val;
  return this;
};

// Usage

const Mod = require('/path/to/mod');

var i1 = new Mod;

var i2 = Mod();

var i3 = new Mod({
  foo: 'bar'
});

var i4 = Mod({
  foo: 'bar'
});

i4.configure('bar', 'baz');

var i5 = (new Mod).configure('bar', 'baz');

編集

Jake Sellers がコメントで指摘したように、これは CommonJS モジュールの標準 API パターンではありません。より良い解決策は、作成しているオブジェクトを返す関数をエクスポートすることです。

さらに重要なことは、構成をプロトタイプに入れることは絶対に勧めないということです。これを行うと、構成オブジェクトがすべての子で共有されます。そのため、それに対する変更はすべての子にも影響します。残念なことに、このくだらないことを書いたとき、私は初心者ではありませんでした。ありがとうジェイク;)

より良い実装:

// Keep defaults private
var defaults = {
  foo : 'foo',
  bar : 'bar'
};

// Construct
var Mod = function Mod (opts) {
  opts = (opts === Object(opts)) ? opts :  {};

  // This allows users to instanciate without the `new` keyword
  if (! (this instanceof Mod)) {
    return new Mod(opts);
  }

  this.config = {};
  // Copy user provided configs to this.config or set to default
  for (var key in defaults) if (defaults.hasOwnProperty(key)) {
    if ({}.hasOwnProperty.call(opts, key)) {
      this.config[key] = opts[key];
    }
    else {
      this.config[key] = defaults[key];
    }
  }
};

// Let the user update configuration post-instanciation
Mod.prototype.configure = function configure (key, val) {
  this.config[key] = val;
  return this;
};

// Export a function that creates the object
exports.createMod = function createMod (opts) {
  return new Mod(opts);
};

// Export the constructor so user is able to derive from it
// or check instanceof
exports.Mod = Mod;

// USAGE

var mod = require('/path/to/mod');

var i1 = mod.createMod({ foo : 'bar' });

i1.configure('bar', 'baz');
于 2013-01-12T14:59:01.090 に答える
1

モジュールのユーザーが事前定義されたインスタンス (で作成したものmodule.exports) を 1 つだけ使用できるようにするか、独自のインスタンスを作成できるようにするかによって異なります (その後、コンストラクターをエクスポートする必要があります)。戻り値ではなく、関数として)。

コンストラクターを作成する場合は、2 番目のオプション (ユーザーにインスタンスを作成させる) を選択します。ただし、それが提供するシングルトン オブジェクトである場合は除きます。

于 2013-01-12T15:02:28.953 に答える