argius note

プログラミング関連

名前空間と自作ライブラリ

JavaScript名前空間とライブラリについて。
たぶん5年くらい「周回」遅れなネタなのではないかと思います。


JavaScript名前空間もしくは変数のスコープの問題が存在し、解決策が多くの方々により研究されているようです。

単純なルールとして、

  • ドメイン名による命名(Javaのパッケージ命名規則のように)
  • 無名関数を使ったローカルスコープの実現

を使うことで、グローバル変数の使用を最小限に抑えることができます。
比較的小規模の開発であれば、これでも良さそうな気がします。主に参照名が長くなってしまうのが欠点です。$をエイリアス用変数として使っています。(JSライブラリでは特殊なオブジェクトに使われることが多いようなので、併用する場合は別のものを使わないといけませんね。)


なお、今回はプロトタイプによる拡張については触れていません。(newしないとprototypeがコピーされないというのを学びました。)

  • ライブラリっぽいもののサンプル
    • IE8,Fx11,GC18で確認
<!DOCTYPE html>
<html>
<body>
<br id="br1" /><hr id="hr1" /><br id="br2" /><hr id="hr2" />
<script language="javascript">

if (!net) var net = {};

net.argius = {};
net.argius.js = {};
net.argius.js.system = {
  p: function(o) { // debug print without console
    document.title = "" + o + "|" + document.title;
  }
};
net.argius.js.collection = {
  a: function() {
    var $ = net.argius.js.collection;
    return new $.Array(arguments);
  },
  asArray: function(o) {
    var $ = net.argius.js.collection;
    if (!o) return new $.Array();
    if (o instanceof net.argius.js.collection.Array)
        return o;
    return new $.Array(o);
  }
};
net.argius.js.collection.Array = function(o) {
  var arr = (o && (o.length || o.length == 0))
          ? o : new Array(Number(o));
  this.array = arr;
  this.length = arr.length;
  this.each = function(f) {
    for (var i = 0; i < this.array.length; i++)
      f(this.array[i]);
  };
  this.concat = function(that) {
    if (!that.length)
      return this;
    var arr = new Array(this.length + that.length);
    for (var i = 0; i < this.length; i++)
      arr[i] = this.array[i];
    var $ = net.argius.js.collection;
    var a = $.asArray(that);
    for (var i = 0; i < a.length; i++)
      arr[this.length + i] = a.array[i];
    return new $.Array(arr);
  };
  return this;
};

(function(){

  var p = net.argius.js.system.p;
  var a = net.argius.js.collection.a;
  var $ = net.argius.js.collection;

  p("START");

  var arr1 = a("1", "2");
  var arr2 = a("3", "4");
  arr1.concat(arr2).each(function(o) { console.log(o); });
  console.log("arr1 instance of argius.Array = "
              + (arr1 instanceof $.Array));
  $.asArray(document.getElementsByTagName("*")).each(
    function(o){ if (o.id) console.log(o.id); });

  p("END");

})();

</script>
</body>
</html>
  • コンソールの出力結果
ログ: 1
ログ: 2
ログ: 3
ログ: 4
ログ: arr1 instance of argius.Array = true
ログ: br1
ログ: hr1
ログ: br2
ログ: hr2