日本野望の会 » Uncategorized http://yabooo.org いずれにせよITで世界征服をたくらむ悪の組織です。 Mon, 28 Dec 2009 14:30:41 +0000 http://wordpress.org/?v=2.8.3 ja hourly 1 入れ替えても読めちゃうツール http://yabooo.org/archives/217 http://yabooo.org/archives/217#comments Fri, 08 May 2009 17:37:55 +0000 http://www.yabooo.org/?p=217 どうも、おひさしぶりです。ひろきのだいちです。

本日こんな記事を見つけて興奮したので、

http://www.asks.jp/users/hiro/59059.html

つい、やっちゃいました。

どうやら、人間は

390 名前:なまえをいれてください[sage] 投稿日:2009/05/08(金) 00:37:47 ID:Oqxr6eLt
こんちには みさなん おんげき ですか? わしたは げんき です。
この ぶんょしう は いりぎす の ケブンッリジ だがいく の けゅきんう の けっか
にんんげは たごんを にしんき する ときに その さしいょ と さいご の もさじえ あいてっれば
じばんゅん は めくちちゃゃ でも ちんゃと よめる という けゅきんう に もづいとて
わざと もじの じんばゅん を いかれえて あまりす。
どでうす? ちんゃと よゃちめう でしょ?

としても読めてしまうみたいなので、ツールというかプログラムにしました。

半角スペース区切りで、ひらがなを入力してください。
適当なので、\sのブラウザごとの違いは吸収してません。
あと、。や?なども一緒くたにシャッフルします。

JAVASCRIPT:
  1. var ShuffledText = Class.create({
  2.     initialize:function(option){
  3.         this.element = $(option.element);
  4.         this.trigger = option.trigger;
  5.         this.target  = $(option.target);
  6.        
  7.         this.element.observe(this.trigger,this.action.bind(this));
  8.     },
  9.     action : function(){
  10.         this.target.value=$A(this.target.value.split(/\s/)).map(function(elem){
  11.             var array = elem.split('');
  12.             var first = array.shift();
  13.             var last  = array.pop();
  14.             return [first,
  15.                 array.sortBy(Math.random),last].flatten().join('')
  16.         }).join(' ');
  17.     }
  18. });

いそいで書いたので、そんなにきれいじゃないんですが
ぜひ遊んでみてください。

追記:
ぐは、なんかもうやられてる
http://blog.livedoor.jp/dankogai/archives/51210157.html

]]>
http://yabooo.org/archives/217/feed 1
Webは進化し続ける。 http://yabooo.org/archives/213 http://yabooo.org/archives/213#comments Tue, 14 Apr 2009 16:52:46 +0000 http://www.yabooo.org/?p=213 yabooo
どうも、ひろきのだいちです。こんにちは。
先月の3/29日にやってきましたよ、「Web2.0中の人ナイト」。
そうそうたる企業の数々が出演しました。
「yahoo!」「mixi」「GREE」「livedoor」「楽天」「クックパッド」「@nifty」。

こんな面子ほかでは見られません。
しかも満員御礼。当日券まで完売の大盛況でした。みなさま本当にありがとうございました。
dsc_0422_s
場所は、@niftyの運営するお台場のライブハウス、「東京カルチャーカルチャー」。

次代を作り上げるには、フツウの場所でフツウに勉強会している場合じゃないんです。

今回出演していただいた20代のエンジニアは、
例外なくみんな目が悪い。
しかし、平均視力0.1の彼らが見据える先にこそ、
ネットはどこまでも広がっている。

平均視力は0.1、WEBエンジニアが見据える世界!「Web2.0 中の人ナイト」ライブレポート(2009.3.29開催)

平均視力よりももっと見てほしいことがある。
それは出演者の平均年齢だ。

出演者はほとんど80's。入社1~2年目のフツウの業界では「右も左もわからないペーペー」と呼ばれている若さだ。彼らみながサービスの第一線で活躍し、うん千万人の日々を支え、そして生活を豊かにし続けている。そう、「WWW」よりも若く、そして学生時代をケータイとともにすごした彼らの見ている地平は、Web2.0といった既存の枠組みを軽くとびこえる。

「webって常に進化して行くものだと思うんです。
だから、個人的には『2.0』も『3.0』も無くて、
webの進化によってみんなの生活が豊かになって行くこと。
これが大事なことなんだと思います」

そしてWebは進化し続ける。

それは、彼らが進化することをやめないからだ。

その他の感想はこちらから

]]>
http://yabooo.org/archives/213/feed 0
書評:JavaScript Good Parts http://yabooo.org/archives/201 http://yabooo.org/archives/201#comments Sun, 21 Dec 2008 16:37:12 +0000 http://www.yabooo.org/?p=201 どうもひろきのだいちです。
水野さん。ありがとう。こんないい本を訳してくれて。そしてくれて。

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

この本はJavaScriptの世界を一段押し上げるためのものです。きっとJGPとか略されたり、蝶本といわれたりとしてこれからJavaScriptの世界でスタンダードとなる概念を構築するための本になるんだろうなと。その意味では仕事でJavaScriptを読む人間に必携の本となるだろうし、この本を「読む」だけではなくて「理解」することが必須となる本となるだろう。

しかし、これはPerlの世界で言うところ「Perl Best Practices」的な書籍ではないということも理解してほしい。

というのもまだ、JavaScriptの世界はPerlほど成熟していないからだ。

この本は「use strict」「use warnings」のための諸概念を切り出すという段階を担っているものであり、
JSLintはその外部実装といったほうがいいのだろうか。

これが荒唐無稽な著者の挑戦でないことは彼がすでに「JSONの規格化」に成功していることからも伺える。

次の段階を考えてみよう。
良いものと悪いものの線引きはできた。

ではその次は悪いものの使いどころと悪い性質の避け方だ。
Perlには「no strict」「no warnings」が用意されていて、悪い面をライブラリユーザに見せずに清潔なプログラミングを可能にしている。

newの使いどころ

newの何がわるいの?

JAVASCRIPT:
  1. function hoge(){
  2.     this.fuga = "x";
  3. }
  4. new hoge(); //{fuga:"x"}

newはjavascriptのクラスシステムの根幹を担うところであり、使わないという選択肢はなかなか難しい。
すべての機能をmethod chainの中に隠蔽してしまうという方法論もあるにはあるが、DOMありきのプログラミングモデルならまだしも、それ以上のものを考える場合には必要最低限の機能である。

なにが悪いのかといえば次のようなケースである。

JAVASCRIPT:
  1. function hoge(){
  2.     this.fuga = "x";
  3. }
  4. hoge(); // undefined, window.fuga="x"

hogeはコンストラクタなのに、new演算子を伴わないで呼び出された場合にfunctionにbindされているthisかあるいはトップレベルオブジェクトに対して汚染をしてしまうケースがある。

これは確かに致命的だ。

ひとつはコーディングルールの中にClass名をHogeのように先頭をcapitalizeするという方法論だ。
もうひとつはコンストラクタ中でチェックルーチンを入れるという方法論。

JAVASCRIPT:
  1. function Hoge(){
  2.     if(this===self)throw('Error');
  3.     this.fuga = "x";
  4. }
  5. Hoge(); // error :Error

あるいは、

JAVASCRIPT:
  1. function Hoge(){
  2.         if(this.constructor!==Hoge)throw('Error');
  3.     this.fuga = "x";
  4. }
  5. var x ={};Hoge.apply(x);

こういった機能の柔軟性を封じるやり方もできる。

本書に出てくるnewをFunctionオブジェクトのmethodとして実装するやり方もエレガントだけど、
もうすでにnewがあるんだからライブラリ作成者なりが注意しておくか、レビューをしっかりすれば問題ナッシングだと思う。

withの使いどころ

JavaScriptからは関数のスコープで定義されるActivation Objectに直接アクセスすることができない。
これはここらへんを読んでもらうとして。

たとえば、Globalオブジェクトをできる限り汚染しないようにして、ネームスペース的機能を提供しようとした場合に

JAVASCRIPT:
  1. window['core'] = {};
  2. (function(){with(this){
  3.     this.fuga = 'text';
  4. }}).apply(window['core']);
  5.  
  6. (function(){with(this){
  7.     print(fuga);
  8. }}).apply(window['core']);

これは適切なnamespace機能さえjavascriptに用意されていれば済む話だが、withが強力な機能を提供する場面でのひとつだ。

eval/new Functionの使いどころ

evalはあらゆる言語で悪者だ。
パフォーマンスを下げてしまうし危険を伴うと紹介されることがおおい。
これに関しておおむね同意した上でもなお、evalを利用することが適切な場面が存在する。

これは皮肉なことにむしろパフォーマンスの分野で。

Webクライアントの技術において、パフォーマンスとはユーザエクスペリエンスのために存在する。つまりユーザがある動作(クリックなど)を行ってから何らかのアクションが発生するまでの時間を最適化したいというニーズが最も多い。

なので、

JAVASCRIPT:
  1. element.onclick = function(){
  2.   for(var i=0,length=BIG_ARRAY.length;i<length;i++){
  3.    //複雑な条件や分岐により重くなる処理
  4.   }
  5. }

のようなプログラムがあったときに

JAVASCRIPT:
  1. dom.ready(function(){
  2.     try{
  3.         window.onclick = new Function([
  4.             '複雑な条件、分岐処理で確定しているものを取り除いたtext'
  5.         ].join(''))
  6.     }catch(e){}
  7. });

のようにしておくことで、DOM構築完了後からimageロードまでの比較的余裕のある時間でスマートな関数を構築しておくことができる。

こういったテクニックは邪道ではあるが、effects.jsなどでも用いられている高速化テクニックの1つであって、JavaScriptというインタラクションのために用いられる言語では重要な要素になりうる。

あくまでもミッションクリティカルな場所でのみ使われるべきではあるが、Templateエンジンなどを実装するためにはevalという邪悪な手段が最適最良のスマートな方法になる。

function文とfunction式

function文とfunction式の違いは、Activationオブジェクトの生成タイミングを理解しておけば間違えることは少ないだろうが、解釈の違いにより問題が起こることは確かにある。

JAVASCRIPT:
  1. //function 文
  2. function hoge(){
  3.     [sample code];
  4. }
  5. //function 式
  6. var hoge = function(){
  7.     [sample code]
  8. }

これらは同値であると説明される場合が多いが以下のようなケースで違いが発生する。

JAVASCRIPT:
  1. (function(){
  2.     var x = 0;
  3.     console.log(hoge);// function hoge(){}
  4.     function hoge(){}
  5. })();
  6.  
  7. (function(){
  8.     var x = 0;
  9.     console.log(hoge);//undefined
  10.     var hoge=function(){}
  11. })();

function文は自動的にスコープの先頭に移動して解釈されるが、function式は解釈されない。

これ自体は小さな問題に見えるが、さらにif文内でのfunction文の巻き取りはjsの実装によって異なりポータビリティを損なうというのが本書の指摘するところだ。

たしかにこれらはポータビリティや保守性を下げる場合がおおい。
しかし、function文がデバッグ性にプラスの要素を与える場合が実はある。

JAVASCRIPT:
  1. Handler = {
  2.     func : (function(){
  3.         function xxx(){}
  4.         return xxx;
  5.     })()
  6. }
  7. console.log(Handler.func); // xxx
  8.  
  9. Handler = {
  10.     func : (function(){
  11.         var xxx = function(){}
  12.         return xxx;
  13.     })()
  14. }
  15. console.log(Handler.func); // function

function文によって作られた関数は処理系内部において"公式な名前"を得ることができる。
公式な名前がある関数は、それが他の関数ではなくて自分自身であることを証明することができる。

この仕様を正式なものとしてなにかプログラムを書くことを推奨はしないが、
この要素が煩雑なプログラムの中で問題箇所を適切に見つけることのできる一因になることがあるということは覚えておいて損はないだろう。

functionは式であれ、文であれこの"公式な名前"をつけられるという性質を知っていると
プロファイル等で

JAVASCRIPT:
  1. $('test').observe('click',function (){
  2.     // 公式な名前の無い関数
  3. });
  4.  
  5. $('test').observe('click',function _anon(){
  6.     // 公式な名前のある関数
  7. });

複数の無名関数の中から、問題の箇所をわずかな変更ですぐに知ることができるかもしれない。
これらはfunction文ではなく、function式であるのでスコープのオブジェクトを汚染することはない。

JAVASCRIPT:
  1. $('button').observe('click',function _anon2(){
  2.     $w('first last').each(function _anon(e){
  3.         //
  4.     });
  5.     console.log(_anon); //is not defined
  6. });
  7. console.log(_anon2); //is not defined

公式に運用するscript中では無用なものではあるかもしれないが、こういった性質によって見えてくる世界もある。

そんなわけでまとめ

・JavaScript Good Partsは仕事でJavaScriptを書くすべてのエンジニアが必読の書である。
・読んだ後、汚いもの/悪いものがどのように使われるべきか考えてみよう
・きれいな世界と汚い世界を分けることでJavaScriptはもっと輝きを増す。

]]>
http://yabooo.org/archives/201/feed 0
新はてぶにフィッシング詐欺の危険性あり! http://yabooo.org/archives/170 http://yabooo.org/archives/170#comments Tue, 25 Nov 2008 05:42:25 +0000 http://www.yabooo.org/?p=170 どうも、ひろきのだいちです。
ソーシャルブックマーク研究会で講演をいたしますので、
ぜひいらしてください。

この記事の内容ははてなおよびJPCERT/CCに連絡いたします。
今しばらくお待ちください。

こういった危険性などについても
12/6 の講演で詳細を発表いたしますのでぜひおたのしみに。

]]>
http://yabooo.org/archives/170/feed 1
再入門JavaScript - 名前空間篇 http://yabooo.org/archives/148 http://yabooo.org/archives/148#comments Tue, 28 Oct 2008 15:13:20 +0000 http://www.yabooo.org/?p=148 おこんばんわ。ひろきのだいちです。
今日は、再入門JavaScriptと題して、Perlなどのサーバサイドの言語になれている方に向けて、
JavaScriptにおける大規模開発の勘所として重要な名前空間の実現方法の解説と、
それらを簡単に提供するライブラリJS.Namespaceを作成しましたので、そのドキュメントを織り交ぜてご紹介します。

JavaScriptを仕事で利用される方や、ライブラリのコピペのような書き方から一歩進みたい方に向けて記述しています。

JAVASCRIPT:
  1. (function(ownNamespace) {
  2. var cache = {};
  3. var MESSAGE ={
  4. NOREF : ':: namespace error ::not found\t',
  5. EXIST : ':: namespace error ::overiding\t',
  6. REQUIRE:':: namespace error ::require\t',
  7. DYNAMIC:':: namespace error ::dynamic'
  8. };
  9. var onwNamespace = _createOrUse(ownNamespace)
  10. Object.extend(ownNamespace),{
  11. createNamespace: export_createNamespace,
  12. isLoaded: export_isLoaded,
  13. depends : export_depends,
  14. dynamic : export_dynamic,
  15. using   : export_using,
  16. wait    : export_wait,
  17. INCLUDE : '/static/js/'
  18. });
  19.  
  20. function _truncateFQN(fqn, n) {
  21. var leaves = fqn.split(".");
  22. var ret = [];
  23. for (var i = 0; i &lt;n ; i++) {
  24. ret.push(leaves[i]);
  25. }
  26. return ret.join('.');
  27. };
  28. function _createOrUse(fqn){
  29. try{
  30. return export_createNamespace(fqn);
  31. }catch(e){
  32. if(e.toString().match(new RegExp(MESSAGE.EXIST))){
  33. return export_using(fqn);
  34. }
  35. }
  36. }
  37. function _getNamespace(fqn) {
  38. if (cache[fqn]) return cache[fqn];
  39. var leaves = fqn.split(".");
  40. var headLeaf = leaves[0];
  41. var tmpTop = window;
  42. var leaveLength = leaves.length;
  43.  
  44. for (var i = 0; i &lt;leaveLength; i++) {
  45. if (!tmpTop[headLeaf]) {
  46. throw new Error(MESSAGE.NOREF + fqn)
  47. }
  48. tmpTop = tmpTop[headLeaf];
  49. headLeaf = leaves[i + 1];
  50. }
  51. return tmpTop;
  52. };
  53. function export_wait(condition,func){
  54. var cond = null
  55. if(Object.isFunction(condition)){
  56. cond = condition;
  57. }
  58. if(Object.isString(condition)){
  59. cond = function(){
  60. try{
  61. return _getNamespace(condition);
  62. }catch(e){
  63. return false;
  64. }
  65. }
  66. }
  67. var check = function(sync){
  68. var obj = null;
  69. if( obj = cond() ){
  70.  
  71. if(!sync){
  72. func.apply(obj);
  73. clearInterval(id);
  74. }else{
  75. return true;
  76. }
  77. }
  78. };
  79. if(check(true))return true;
  80. var id = setInterval( check, 30 );
  81. }
  82. function export_createNamespace(fqn, func) {
  83. var leaves = fqn.split(".");
  84. var headLeaf = leaves[0];
  85. var tmpTop = window;
  86. var leaveLength = leaves.length;
  87. if (cache[fqn]) throw (MESSAGE.EXIST + fqn);
  88. for (var i = 0; i &lt;leaveLength; i++) {
  89. if (tmpTop[headLeaf] &amp;&amp; typeof tmpTop[headLeaf] != "object") {
  90. throw new Error(MESSAGE.EXIST  + typeof tmpTop[headLeaf] + ". : " + fqn);
  91. }
  92. tmpTop[headLeaf] = tmpTop[headLeaf] || {};
  93. cache[_truncateFQN(fqn, i)] = tmpTop;
  94. tmpTop = tmpTop[headLeaf];
  95. headLeaf = leaves[i + 1];
  96. }
  97. if (func) {
  98. return func.apply(tmpTop);
  99. } else {
  100. return tmpTop;
  101. }
  102. }
  103. //
  104. function export_dynamic(fqn,func){
  105. var ns;
  106. try{
  107. return export_using(fqn,func);
  108. }catch(e){
  109. var url = ownNamespace.INCLUDE +fqn.replace(/\./g,'::').underscore()+'.js';
  110. new Ajax.Request(url,{
  111. method :'get',
  112. onComplete:function(r){
  113. ns = export_using(fqn,func);
  114. },
  115. onException:function(r,a){
  116. throw new Error(  MESSAGE.DYNAMIC + fqn );
  117. }
  118.  
  119. })
  120. }
  121. }
  122. function _getExportedObject(list,ns){
  123. var obj = {};
  124. var flag = false;
  125. $A(list).each(function(arg){
  126. flag = true;
  127. if(ns[arg]){
  128. obj[arg] = ns[arg];
  129. }else{
  130. throw(new Error('cant export'));
  131. }
  132. });
  133. return (flag)?obj:ns;
  134. }
  135. function export_using(fqn,funcOrExport) {
  136. var ns = _getNamespace(fqn);
  137. if(funcOrExport){
  138. if(Object.isFunction(funcOrExport)){
  139. var func = funcOrExport;
  140. var obj  = _getExportedObject( func.argumentNames(),ns );
  141. return func.apply(obj,func.argumentNames().map(function(arg){return obj[arg];}));
  142. }
  143. if(Object.isArray(funcOrExport)){
  144. return _getExportedObject(funcOrExport,ns);
  145. }
  146.  
  147. }else{
  148. return ns;
  149. }
  150. };
  151. function export_isLoaded(){
  152. try{
  153. return export_depends.apply(this,arguments);
  154. }catch(e){
  155. return false;
  156. }
  157. }
  158. function export_depends() {
  159. var fqn = $A(arguments).flatten();
  160. var ret = [];
  161. try{
  162. for(var i=0,l = fqn.length;i
  163. if (_getNamespace(fqn[i])) {
  164. ret.push( _getNamespace(fqn[i]));
  165. }
  166. }
  167. }
  168. catch(e){
  169. throw new Error(  MESSAGE.REQUIRE + fqn.join(",")+"/"+e.message );
  170. }
  171. if(ret.length == 1){
  172. return ret[0];
  173. }else{
  174. return ret;
  175. }
  176. };
  177.  
  178. })('JS.Namespace');

]]>
http://yabooo.org/archives/148/feed 1
再入門JavaScript - 動的ローディング http://yabooo.org/archives/145 http://yabooo.org/archives/145#comments Tue, 28 Oct 2008 15:06:24 +0000 http://www.yabooo.org/?p=145 動的ロード

サーバサイドにおいては、フレームワークなどの汎用的に使われるライブラリやプラグイン機構などでしか目にすることが
あまりないモジュールの動的ロードですが、クライアントサイドのようにユーザインタフェースと直結したプログラミング環境においては
動的ローディングは重要な技術です。

Perlにおいてコンパイルフェーズ以外でモジュールのロードを行いたい場合、UNIVERSAL requireを用いることが多いです。

PERL:
  1. use UNIVERSAL qw(require);
  2. sub get_class{
  3.    my $package = shift;
  4.    $package->require;
  5. }

JavaScriptにおいて動的ローディングを行うためには2つの方法があります。
ひとつはDOM操作によってscriptタグを埋め込む方法で
もうひとつはXML.HTTPRequestによって取得したTextをEvalする方法です。

DOM操作による動的ロード

JAVASCRIPT:
  1. $$('head')[0].appendChild(new Element('script',{src:'/static/js/dynamic/load.js'}));

XHRによる動的ロード

JAVASCRIPT:
  1. new Ajax.Request('/static/js/dynamic/load.js',{
  2. evalScript:true,
  3. onSuccess:function(e){
  4.   // 
  5. },
  6. onException:function(e){
  7.   //
  8. }
  9. });

ライブラリによる動的ロード

動的ロードの縛りとして、

* 確実に終了と例外を補足できるXHRのみでのダイナミックロードに限定する
* urlでなく完全限定名を引数としてそれをファイルパスに自動変換した場所のファイルを取得する
* 内部でそのモジュールが作成されている

をもうけることで安全な動的ロードを提供する。

JAVASCRIPT:
  1. JS.Namespace.dynamic('XXX.YYY.ZZZ',function(aaa){
  2.     aaa();
  3. });

]]>
http://yabooo.org/archives/145/feed 1
再入門JavaScript – 名前空間上の関数をExport http://yabooo.org/archives/143 http://yabooo.org/archives/143#comments Tue, 28 Oct 2008 15:05:00 +0000 http://www.yabooo.org/?p=143 名前空間上の関数を利用する

Perlの場合、Exporterなどの仕組みを使えば

PERL:
  1. use XXX::YYY::ZZZ qw(aaa bbb);
  2.  
  3. aaa();

のように記述するだけで、Current Packageにそれぞれの関数を貼り付けることができます。

あるいは

PERL:
  1. use XXX::YYY::ZZZ;
  2.  
  3. &XXX::YYY::ZZZ::aaa();

のように、完全限定名(Full Qualified Name)でアクセスすることでもその名前空間上のメソッドを利用することができます。

jsの場合では完全限定名を利用すれば同じように利用することができます。

JAVASCRIPT:
  1. XXX.YYY.ZZZ.aaa();

一方、Exporterのように現在のスコープに貼り付けるにはwithブロックを使います。

JAVASCRIPT:
  1. (function(){with(XXX.YYY.ZZZ){
  2.    aaa();
  3. }})();

しかし、withの動作をしっかり把握できない場合にwithを多用することはjavascriptのプログラム作法からは
推奨されません。

そのかわりに一時的にその名前空間をテンポラリな変数に別名をつけて利用することもできます。

JAVASCRIPT:
  1. (function(){
  2.    var ns = XXX.YYY.ZZZ;
  3.    ns.aaa();
  4. })();
  5.  
  6. (function(){
  7.    this.aaa();
  8. }).apply(XXX.YYY.ZZZ);

どちらも、問題なく動作します。

JS.Namespaceライブラリではこれらの利便性を考えて

JAVASCRIPT:
  1. JS.Namespace.using('XXX.YYY.ZZZ',function(){
  2.    this.aaa();
  3. });
  4.  
  5. var ns = JS.Namespace.using('XXX.YYY.ZZZ');
  6. ns.aaa();

などの記述を可能にします。

またネームスペース自体に追記がなく、use XXX qw(hoge)のようにただ関数やオブジェクトを利用するだけの場合

JAVASCRIPT:
  1. var ns = JS.Namespace.using('XXX.YYY.ZZZ',$w('aaa bbb'));
  2. ns.aaa();
  3. ns.test = "test"; // XXX.YYY.ZZZは汚染されない
  4.  
  5. //クロージャの引数として宣言したオブジェクトを引き渡す
  6. JS.Namespace.using('XXX.YYY.ZZZ',function(aaa,bbb){
  7.     aaa();
  8. });

このように記述することができます。

jsには予約語としてnamespaceが定義されているけどブラウザじゃ使えませんし、Rhinoなどの一部の処理系を除いて、意味を成さないんですが、var namespace = hogehoge;みたいな記述は避けてください。

]]>
http://yabooo.org/archives/143/feed 0
再入門JavaScript – 名前空間 http://yabooo.org/archives/139 http://yabooo.org/archives/139#comments Tue, 28 Oct 2008 15:00:51 +0000 http://www.yabooo.org/?p=139 ネームスペース

ネームスペースとはwikipedia先生いわくこんな感じです。

名前の集合を分割することで衝突の可能性を低減しつつ参照を容易にする概念である。

Perlであれば

PERL:
  1. package XXX::YYY::ZZZ;
  2.  
  3. sub aaa{
  4.  
  5. }
  6. sub bbb{
  7.  
  8. }

とすれば、aaa,bbbはシンボリックテーブルXXX::YYY::ZZZ::において
XXX::YYY::ZZZ::aaa,XXX::YYY::ZZZ::bbbとして記録されグローバルに参照することができます。

なので仮に

PERL:
  1. package AAA;
  2.  
  3. sub aaa{
  4.  
  5. }
  6. sub bbb{
  7.  
  8. }

というモジュールをロードしても、名前は衝突することがありません。

JavaScriptの場合、シンボリックテーブルのようにstrictプラグマで保護されているようなグローバルハッシュは存在しないので
window以下のグローバルオブジェクトを使い名前空間を構築するほかありません。

JAVASCRIPT:
  1. (function(){
  2.     window.XXX = XXX || {};
  3.     window.XXX.YYY = XXX.YYY || {};
  4.     window.XXX.YYY.ZZZ = XXX.YYY.ZZZ || {};
  5.     window.XXX.YYY.ZZZ.aaa = function(){};
  6.     window.XXX.YYY.ZZZ.bbb = function(){};
  7. })();

しかし、このように記述していては冗長すぎるので、

JAVASCRIPT:
  1. var XXX = XXX || {};
  2. XXX.YYY = XXX.YYY || {};
  3. XXX.YYY.ZZZ = XXX.YYY.ZZZ || {};
  4.  
  5. (function(){
  6.     this.aaa = function(){};
  7.     this.bbb = function(){};
  8. }).apply(XXX.YYY.ZZZ);

のように書くことで、クロージャ内のスコープにおいて、thisがXXX.YYY.ZZZとなり、冗長な記述を避けることができます。

また、Prototype.jsのObject.extendを利用すれば

JAVASCRIPT:
  1. (function(){
  2.     Object.extend(this,{
  3.         aaa:export_aaa,
  4.         bbb:export_bbb
  5.     })
  6.     function export_aaa(){};
  7.     function export_bbb(){};
  8.    
  9. }).apply(XXX.YYY.ZZZ);

明示的にレキシカルスコープ中のどのメソッドを名前空間オブジェクトにバインドするかを記述することができます。

一方、

JAVASCRIPT:
  1. var XXX = XXX || {};
  2. XXX.YYY = XXX.YYY || {};
  3. XXX.YYY.ZZZ = XXX.YYY.ZZZ || {};

この部分の記述の冗長さは付きまとってしまうので、

これら名前空間に関する処理をひとつにまとめるメソッドをJS.Namespace

JAVASCRIPT:
  1. var ns =JS.Namespace.createNamespace('XXX.YYY.ZZZ');
  2. ns.aaa=function(){};
  3. ns.bbb=function(){};
  4.  
  5. or
  6.  
  7. JS.Namespace.createNamespace('XXX.YYY.ZZZ',function(){
  8.     Object.extend(this,{
  9.         aaa:export_aaa,
  10.         bbb:export_bbb
  11.     })
  12.     function export_aaa(){};
  13.     function export_bbb(){};
  14. });

のように記述することができます。

createNamespaceは新しいネームスペースを定義することを明示している関数です。
なので、すでにそのネームスペース/オブジェクトが存在している場合エラーを出力します。

これはファイル名とパッケージの結びつきの小さいjsにおいて、

* 名前空間を定義する場面
* その空間に関数/クラスを追加する場面
* その名前空間上の関数を利用する場面

というのをある程度明示しておくことで、開発上の混乱を避けるためです。

では次に名前空間に定義された関数を利用する場面での記述を考えて見ましょう。

]]>
http://yabooo.org/archives/139/feed 1
再入門JavaScript – モジュールの依存関係 http://yabooo.org/archives/135 http://yabooo.org/archives/135#comments Tue, 28 Oct 2008 14:56:58 +0000 http://www.yabooo.org/?p=135 依存関係のチェック

AAAというモジュールを利用して、BBBというモジュールを作成したいケースを考えてみると

PERL:
  1. use AAA;

Perlでは上記のように書けば、動的にincludeパスを探索し、モジュールのロードと依存関係の解決を
してくれますが、Jsではそんな便利な仕組みは存在しません。

また、HTTPリクエスト数の問題などからファイル名とモジュール名とを完全に同期させることも
非常に難しい課題です。

だからといって、jsのモジュールに

JAVASCRIPT:
  1. /*
  2. * require BBB
  3. *
  4. */

と書いたところで、このコメントはプログラムから解釈されないのですぐにエラーを出してくれませんし、
コメント自体の正しさを保障してくれません。

なので、

JAVASCRIPT:
  1. if( !BBB )throw('ERROR!');

のようにコード中に依存関係を明示的に書くようにすれば、そのモジュールがロードされて無い場合すぐに気付くことができます。

JS.Namespaceライブラリでは

JAVASCRIPT:
  1. JS.Namespace.depends('BBB','AAA.WWW');

このように記述することで、依存関係のチェックをコード中に埋め込むことができます。

]]>
http://yabooo.org/archives/135/feed 1
再入門JavaScript – Scopeを作る http://yabooo.org/archives/133 http://yabooo.org/archives/133#comments Tue, 28 Oct 2008 14:55:34 +0000 http://www.yabooo.org/?p=133 スコープ

javascriptにはPerlのようにレキシカルブロックが明示的に提供されていません。
なので、

JAVASCRIPT:
  1. var i = 0;
  2.  
  3. {
  4.     var i = i;
  5.     i++;
  6.     i++;
  7.     console.log(i); // 2であってほしい
  8. }
  9. console.log(i); // 0であってほしい

このようにはかけません。
もしレキシカルにスコープを生成したい場合にはクロージャを使います。

JAVASCRIPT:
  1. var i = 0;
  2.  
  3. (function(){
  4.     var i = window.i;
  5.     i++;i++;
  6.     console.log(i);
  7. })();
  8. console.log(i);

上記のプログラムはfunction(){}として、無名のクロージャを生成してそのまま実行しています。

ちなみにPerlのレキシカルスコープと少し異なるのは関数の宣言に関してです。

PERL:
  1. # in perl
  2. package XXX;
  3.  
  4. {
  5.   my $val = undef;
  6.   sub get_val{
  7.      return $val;
  8.   }
  9. }

この場合、get_valはCurrent Packageである、XXXのシンボリックテーブルに記憶されますが

JAVASCRIPT:
  1. (function(){
  2.     var val = undefined;
  3.     function getValue(){
  4.         return val
  5.     }
  6.  
  7. })();
  8.  
  9. getValue(); // 関数が見つからない。

javascriptの場合、packageの概念は無いので、レキシカルスコープにはりつきます。

JAVASCRIPT:
  1. var XXX = {};
  2. (function(){
  3.     var val = 11;
  4.     function getValue(){
  5.         return val
  6.     }
  7.     XXX.getValue = getValue;
  8.  
  9. })();
  10.  
  11. XXX.getValue();

レキシカルスコープ上の関数を外部から参照可能にするためにはグローバルから参照可能な
オブジェクトに対して明示的に貼り付けてやる必要があります。

また、
JavaScriptの場合、ファイルベースのレキシカルスコープは存在しないので、
複数のJSの読み込まれているページの場合、それぞれのJSは明示的に
レキシカルスコープを作成する必要があります。

]]>
http://yabooo.org/archives/133/feed 2