タイトルの通りです。例えば以下のような独自定義関数があったとします:
// n 未満の素数を配列で取得する関数
function pnum( n ){
  var results = [];

  for( var i = 2; i < n; i ++ ){
    var b = true;
    for( var j = 2; j < i && b; j ++ ){
      b = i % j;
    }
    if( b ){
      results.push( i );
    }
  }

  return results;
}

関数名は pnum() 、パラメータを1つ受け取り、その値未満の素数配列を返す、という内容です。関数の処理内容はもっと複雑でも構いません。

例えば上記内容を pnum.js というファイルで保存した場合、同じフォルダにある HTML ファイルから以下のように使うことができます:
<script src="./pnum.js"></script>
<script>
var results = pnum( 1000 );  // 1000 未満の素数の配列
</script>

では同じファイルの同じ関数を Node.js からも使いたくなった場合はどうすればいいでしょう? あるいは逆に Node.js から require や import で使える JavaScript ファイルをブラウザから読み込んで使いたい場合はどうすればいいでしょう? これが今日のブログテーマです。


答えはシンプルなんですが、まず Node.js から使う場合は、このようにクラス化して、クラスを export するのが定番的なやり方だと思っています:
class MyClass {
  constructor(){
  }

  pnum( n ){
    var results = [];

    for( var i = 2; i < n; i ++ ){
      var b = true;
      for( var j = 2; j < i && b; j ++ ){
        b = i % j;
      }
      if( b ){
        results.push( i );
      }
    }

    return results;
  }
}

module.exports = MyClass;

この上の内容を myclass.js という名前で保存したとすると、Node.js の呼び出し元からは以下のようにして利用することができます:
var MyClass = require( './myclass' );
var myClass = new MyClass(); var results = myClass.pnum( 1000 );

では同じ myclass.js をブラウザの JavaScript から <script> タグで使えばいいのでは・・・ と思いますが、その場合は myclass.js の最終行である module.exports = MyClass; の所でエラーになります(module が定義されていないからです)。

そこでこのエラーを回避するために以下のようにします。module が object として定義済みである場合のみ最終行を実行するようにします:
class MyClass {
  constructor(){
  }

  pnum( n ){
    var results = [];

    for( var i = 2; i < n; i ++ ){
      var b = true;
      for( var j = 2; j < i && b; j ++ ){
        b = i % j;
      }
      if( b ){
        results.push( i );
      }
    }

    return results;
  }
}

if( typeof module === 'object' ){
  module.exports = MyClass;
}

こうしておくとブラウザ側も Node.js と同様に実行することができます:
<script src="./myclass.js"></script>
<script>
var myClass = new MyClass();
var results = myClass.pnum( 1000 );
</script>

要は「クラス化して、module が object として定義済みであればクラスをエクスポート指定」することで Node.js からもブラウザ JavaScript からも共通利用できるようになります。