社内の煎り大豆ブームの火付け役。agoです。
今日はjavascriptで名前空間を有効活用する方法をご紹介したいと思います。
1 無名関数の即実行
無名関数をその場で実行することで名前空間を閉じることができます。
(function () {
// hogeはこのfunction内のみ参照可能
var hoge = 1;
})();
また、newを使用した方法でも実行可能です。
new function () {
// hogeはこのfunction内のみ参照可能
var hoge = 1;
};
それぞれ違いは以下の通りです。
- ()()
- thisがwindow
- returnしたものをそのまま受け取れる
- new
- thisが空Object
- Object以外をreturnした場合this
引数を渡す場合、それぞれ以下のようなかたちで渡す事が可能です。
(function (arg1, arg2, arg3) {
console.log(arg1, arg2, arg3);
// => 1 2 3
})(1, 2, 3);
new function (arg1, arg2, arg3) {
console.log(arg1, arg2, arg3);
// => 1 2 3
}(1, 2, 3);
newを使用するとreturnする値の扱いが面倒になるので、値を返したい場合は()()方式を使用することをお勧めします。
また、両方ともthisは引き継がれないので、内部でthisが必要な場合、あらかじめvar self = this;等で待避する必要があります。
2 function objectのpropertyに保持
あるfunctionに関連した値を保持したい場合、そのfunctionのpropertyとして値を保持する方法もあります。
function hoge () {
// function定義と同時に初期化できないので注意
hoge.huga = hoge.huga ? hoge.huga + 1 : 1;
console.log(hoge.huga);
};
hoge();
// => 1
hoge();
// => 2
hoge();
// => 3
hoge();
// => 4
hoge();
// => 5
...
この方法の場合、以下のような利点、欠点があります。
- 利点
- 無名関数で囲む方法に比べてインデントが浅くなる
- 専用のobjectを用意する場合に比べて必要な変数が少ない
- 名前空間的に閉じているが、外部からアクセス可能(欠点でもあります)
- 欠点
- functionを再定義すると変数が消える
- functionをコピーする場合、propertyもコピーする必要がある
- 外部から変更されてしまう(利点でもあります)
jQueryの$もこの方法を使うことにより、「$()で実行可能な上に$.browserでも使えるobject」を実現しています。
3 html elementのpropertyに保持
あるhtml elementに関連した値を保持したい場合、そのhtml elementのpropertyとして値を保持する方法もあります。
var elem = document.getElementById('hoge');
elem.hoge = 1;
console.log(elem.hoge);
// => 1
各要素に状態を保持する場合、classNameが使用されることもありますが、もし単純に変数を保持したいだけであればこの方法の方が簡単ではないかと思います。
ただし、tagName等の予約された名前は使用できないので注意してください。
また、この方法はDOMの変更が発生するため、他の方法に比べて速度的に不利になります。
4 $().dataに保持する
これはjQueryを使える場合に限定されますが、$().dataを使用することでhtml elementに変数を保持することが可能です。
$('selector').data('hoge', '1');
console.log($('selector').data('hoge'));
// => 1
内部的には各html elementsにuniqなidを振って、そのidを内部のhash keyとして使用することで実装されています。
できることは3とそれほど違いはないのですが、「tagName等の名前予約された属性名も使用可能」、「速度的に有利」等の違いがあります。 (ただし、events、handlerはjQuery上予約されているので使用しないよう注意してください)