RingoJSのチュートリアルをやってみる 2日め

今日もRingoJSのチュートリアルをやってみます。あんまり時間がとれないので少しずつやってます。

JavaScript Modules

自分で書いたJavaScriptファイルを、他のプロジェクトから使うときのやり方が書いていました。

モジュールを輸出する - exports

まず、使われる側は、公開したい関数を exports というグローバル変数(?)のプロパティに代入します。
すると、他のプログラムは、エクスポートされた関数を使用できるようになります。逆に exports にセットしていない関数や変数は他から見えないので、グローバル名前空間が汚れるのを気にする必要がありません。素晴らしいですね。

// mymodule.js

// 外部に公開する関数
exports.sayHello = function() {
  print('Hello World!');
};

// 公開しない関数
function sayButuButu() {
  print('Ore nanka do-se...');
}
モジュールを要求する - require

モジュールを使う側は require() 関数を使います。
引数にはモジュールのファイル名から「.js」を除いた文字列を渡します。require()関数は、読み込んだファイルの中のexports変数を戻り値として返します。exports変数にはモジュールが公開した関数だけが入っているので、呼び出し側は公開されている関数だけを使うことができるわけです。

var mymodule = require('mymodule');

mymodule.sayHello(); // OK
mymodule.sayButuButu(); // エラー!
モジュールの一部だけをrequire

JavaScriptの新しい文法を使って、モジュールが公開している関数の一部だけを、直接取り出して使うことができます。この書き方は初めて見たのでびっくりしました。

var {sayHello} = require('mymodule');
sayHello();

JavaScriptの文法も変わっていくのですねえ。
↓にいろいろ載っていました。英語が得意な人は読んでみて私に教えてください><。
New in JavaScript 1.7 - MDC

モジュールを自身に含める - include

モジュールを使う手段に include() 関数というのが用意されています。
require()と同じようにモジュールのファイル名(- .js)を渡して実行するのですが、exports変数にセットされた関数たちを、自分とこの名前空間に展開します。ローカル変数とか、名前がかぶっていたりすると、知らないうちに上書きされたりして危険な感じがします。Ringoシェルで対話的に実行するときだけ使うのがよいみたいです。

include('mymodule');

sayHello(); // OK
sayButuButu(); // エラー!
モジュールのファイルを探すパス

require.paths 配列にパス文字列の配列が入っています。これにパスを追加してあげれば、そこにあるファイルをモジュールとして探すようになります。

>> require.paths
/Users/makoto/work/lang/javascript/ringojs/ringojs/apps/demoblog/,/Users/makoto/work/lang/javascript/ringojs/ringojs/modules/,/Users/makoto/work/lang/javascript/ringojs/ringojs/packages/namespace-skeleton/lib/
>> require.paths.unshift('/path/to/modules');
4

余談ですが、include.pathsには何も入っていませんでした。

思ったこと

モジュールの仕組みを使うと、クロージャっぽいものがすっきりと書けるようになるんじゃないかと思いました。

var trueOnlyFirstTime = (function() {
  var b = true;
  return function() {
    if (b) {
      b = false;
      return true;
    }
    return false;
  };
})();

最初の一回だけtrueを返して二回目以降はfalseを返す関数 - syttruの日記

上のような、ファンクションファンクションしていてよくわからなかったコードが、こんな感じで書けます。

var b = true;
exports.trueOnlyFirstTime = function() {
  if(b) {
    b = false;
    return true;
  }
  return false;
};

ちょっと見通しがよくなったんじゃないでしょうか。どうでしょう。


今日はここまで。