English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

nodejsのexportsとmodule.exportsの違いの詳細解説

require はコードをロードするために使用され、exports と module.exports はコードをエクスポートするために使用されます。しかし、多くの初心者が exports と module.exports の違いに迷うことがあります。exports と module.exports の関係をよりよく理解するために、まず js の基礎を強化しましょう。例:

app.js

var a = {name: 'nswbmw 1};
var b = a;
console.log(a);
console.log(b);
b.name = 'nswbmw 2;
console.log(a);
console.log(b);
var b = {name: 'nswbmw 3};
console.log(a);
console.log(b);

app.js を実行すると、以下の結果が得られます:

{ name: 'nswbmw 1}
{ name: 'nswbmw 1}
{ name: 'nswbmw 2}
{ name: 'nswbmw 2}
{ name: 'nswbmw 2}
{ name: 'nswbmw 3}

説明します:a はオブジェクトであり、b は a の参照であり、つまり a と b が同じオブジェクトを指している、つまり a と b が同じメモリアドレスを指しているため、最初の2つの出力が同じです。b に対して変更を行うと、a と b が指している同じメモリアドレスの内容が変更されるため、a も影響を受け、したがって3番目と4番目の出力が同じです。b を完全にオーバーライドすると、b は新しいメモリアドレスを指すようになります(元のメモリブロックには変更が加えられていません)、a は元のメモリブロックを指し続けています、つまり a と b が同じメモリアドレスを指していないため、最後の2つの出力が異なります。

上記の例を理解した後、本題に入りましょう。

exports と module.exports の違いを知るために、以下の3点を知っておく必要があります:

  • exports は module.exports に指している参照です。
  • module.exports の初期値は空のオブジェクト {} で、したがって exports の初期値も {} です。
  • require() は module.exports ではなく exports を返します

したがって、私たちは以下のように

var name = 'nswbmw';
exports.name = name;
exports.sayName = function() {
 console.log(name);
}

exports に値を代入することは、実際には module.exports という空のオブジェクトに二つの属性を追加することに過ぎません。上記のコードは以下のように相当します:

var name = 'nswbmw';
module.exports.name = name;
module.exports.sayName = function() {
 console.log(name);
}

私たちは通常以下のように exports と module.exports を使用します

円の面積を計算する簡単な例:

exports の使用

app.js

var circle = require('./circle');
console.log(circle.area(4));

circle.js

exports.area = function(r) {
 return r * r * Math.PI;
}

module.exports の使用

app.js

var area = require('./area');
console.log(area(4));

area.js

module.exports = function(r) {
 return r * r * Math.PI;
}

上記の二つの例の出力は同じです。どうしてこんな書き方ができないのかと疑問に思われるかもしれません。

app.js

var area = require('./area');
console.log(area(4));

area.js

exports = function(r) {
 return r * r * Math.PI;
}

上記の例ではエラーが発生します。これは、前の例では exports に属性を追加することで、exports 指向のメモリにのみ変更が加えられたため、

exports = function(r) {
 return r * r * Math.PI;
}

実際には exports が上書きされているということで、つまり exports は新しいメモリ(円の面積を計算する関数の内容を持つ)を指している、つまり exports と module.exports は同じメモリを指していない、つまりその時点で exports と module.exports は何の関係もなく、つまり module.exports が指しているメモリには何も変更されていない、つまりそれが空のオブジェクト {} である、つまり area.js は空のオブジェクトをエクスポートしているので、app.js で area を呼び出すと、4TypeError: object is not a function のエラーが報告されます。

したがって、一言でまとめると:モジュールがオブジェクトを导出する場合、exports と module.exports をどちらも使用できます(ただし、exports は新しいオブジェクトにオーバーライドすることはできません)、非オブジェクトのインターフェースを导出する場合、module.exports にのみオーバーライドする必要があります。

私たちはよくこのような書き方を見かけます:

exports = module.exports = somethings;

上記のコードは以下のように等価です

module.exports = somethings;
exports = module.exports;

理由はとても単純で、module.exports = somethings は module.exports をオーバーライドしています。この時、module.exports と exports の関係が切れて、module.exports は新しいメモリブロックを指し、exports は元のメモリブロックを指しています。module.exports と exports が同じメモリブロックや同じ「オブジェクト」を指すようにするため、exports = module.exports としました。

これでこの記事のすべてが終わりです。この記事の内容が皆さんの学習や仕事に少しでも役立つことを願っています。また、ナイアラチュートリアルを多くサポートしてください!

声明:この記事の内容はインターネットから収集され、著作権者によって所有されています。インターネットユーザーによって自発的に貢献し、自己でアップロードされたものであり、このサイトは所有権を持ちません。また、人工的な編集は行われていません。著作権侵害が疑われる内容を見つけた場合は、メールを notice#w までお送りください。3codebox.com(メールの際は、#を@に変更してください)で通報し、関連する証拠を提供してください。一旦確認がついたら、このサイトは即座に侵害疑いのコンテンツを削除します。

基本教程
おすすめ