書評:JavaScript Good Parts

Monday, 22. December 2008 von hiroki_daichi

どうもひろきのだいちです。
水野さん。ありがとう。こんないい本を訳してくれて。そしてくれて。

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はもっと輝きを増す。

【告知】日本野望の会 忘年会 2008

Monday, 08. December 2008 von pinkmac

名称未設定-1.jpg

2008年の野望会は新年会にはじまり、忘年会に終わる…
野望会おなじみの居酒屋ライトニングトーク、全員自己紹介、
今回もやります。奮ってご参加ください。

実施要綱

  • 日時 2008/12/20(土)18:00~20:00
  • 場所 渋谷 素材屋 宮益坂店 http://r.gnavi.co.jp/g084612/
  • 会費 4,500円
  • 定員 20名

LTについて

  • 制限時間 1人5分
  • テーマ  2008年わたしの野望(技術ねたでもそうでなくても)
  • LT登壇希望の方はコメント欄にその旨ご記入ください。
  • PCは主催側でも用意します。

参加表明はこちらからお願いします。
http://atnd.org/events/218

SBM研究会発表資料を公開します

Saturday, 06. December 2008 von hiroki_daichi

普通のやつらのメタを行け

パワポです。すこし長いので、はしょりながらやります。

普通に前半のほとんどはフロントエンドの技術を理解している人なら当たり前すぎる内容ですが、
研究会が比較的バックエンドよりなので、こういう話もやってもいいかなと。

あ、

野望イベント近日公開です。

興味のある方はぜひこちらのブログをチェックしてください。

slideshare --

Safari/Webkitのおせっかいキャッシュとその対策。

Saturday, 29. November 2008 von hiroki_daichi

どうもひろきのだいちです。

最近のモダンなブラウザには、Backfowardキャッシュと呼ばれるブラウザの戻るボタンを押した際に利用されるキャッシュ機構が用意されています。この機構は普段ウェブブラウジングを行う際には間違った操作からの復帰が早く非常に重宝するのですが、一部のWebアプリケーション設計の際にはこの仕組みが厄介に働くことがあります。

(more...)

新はてぶにフィッシング詐欺の危険性あり!

Tuesday, 25. November 2008 von hiroki_daichi

どうも、ひろきのだいちです。
ソーシャルブックマーク研究会で講演をいたしますので、
ぜひいらしてください。

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

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

YAMLってたべれるの?

Thursday, 13. November 2008 von pinkmac

おひさしぶりです。へたれのこみや(pinkmac)です。
YAMLとは何かを今更知ったので、覚え書きしておきます。
折角なので他のデータ形式もいっしょに見直してみることにしました。

サンプルデータ on XML

XML:
  1. <zgundam>
  2.     <organization name="エゥーゴ">
  3.         <person>
  4.             <name>カミーユ・ビダン</name>
  5.             <ms>Zガンダム</ms>
  6.         </person>
  7.         <person>
  8.             <name>クワトロ・バジーナ</name>
  9.             <ms>百式</ms>
  10.         </person>
  11.     </organization>
  12.     <organization name="ティターンズ">
  13.         <person>
  14.             <name>パプテマス・シロッコ</name>
  15.             <ms>ジ・O</ms>
  16.         </person>
  17.         <person>
  18.             <name>レコア・ロンド</name>
  19.             <ms>パラス・アテネ</ms>
  20.         </person>
  21.     </organization>
  22.     <organization name="アクシズ">
  23.         <person>
  24.             <name>ハマーン・カーン</name>
  25.             <ms>キュベレイ</ms>
  26.         </person>
  27.     </organization>
  28. </zgundam>

思いっきり偏ったサンプルで恐縮ですが、、
このデータ構造を、YAML、ついでにJSONで書いてみたいと思います。
(more...)

再入門JavaScript -目次-

Wednesday, 29. October 2008 von hiroki_daichi

こんにちは、ひろきのだいちです。

JavaScriptの再発見からさらに2年がたち、モダンなWeb開発では欠かせない存在となったJavaScript。さまざまなライブラリが乱立し、言語としての基礎を得ないままでもある程度のアプリケーション開発ができるようになった現在。

再入門JavaScriptと題して、中上級者を目指すために入門書を超えてじっくりとJavaScriptを学びなおすことが重要だと考え、ここを中心にまとめていきたいと思います。

ここで掲載するトピックは本当の基礎の基礎は他の媒体にゆだねた上で、「仕事でつかえる」レベルのコードを記述するために重要で比較的高度なものを取り扱うつもりです。

また、ここでいう仕事で使えるとは"多人数で開発を進める"ことを前提とした開発環境を想定しており、他サイトのAPIの使い方やライブラリの使用方法といった枝葉のリファレンスではありません。

また、ここに書かれていることはたいてい僕のメモなので、責任はもちませんw

再入門JavaScript -フロントエンドエンジニア資料集

再入門JavaScript -JavaScriptでの中大規模開発

  • 再入門JavaScript - コード成長過程
  • 再入門JavaScript - MarkupエンジニアとScriptエンジニア、サーバサイドエンジニアとの協調
  • 再入門JavaScript - グレースフルデグラデーション
  • 再入門JavaScript - MVCモデル
  • 再入門JavaScript -  クライアントサイドMVC
  • 再入門JavaScript -  デザインパターン

再入門JavaScript -名前空間とスコープ

再入門JavaScript -オブジェクト指向と関数オブジェクト

  • 再入門JavaScript - オブジェクトとプロトタイプチェーン
  • 再入門JavaScript - 継承・ダックタイピング
  • 再入門JavaScript - 引数アサーションと動的ヴァリデーション
  • 再入門JavaScript - 動的バインディング
  • 再入門JavaScript - ビルドインオブジェクトのプロトタイプ拡張

再入門JavaScript -DOM

  • 再入門JavaScript - イベントとバブリング
  • 再入門JavaScript - XHTML拡張
  • 再入門JavaScript - CSSの扱い

再入門JavaScript -DOM上のDSL

  • 再入門JavaScript - CSS Selector
  • 再入門JavaScript - XPath
  • 再入門JavaScript - E4X

再入門JavaScript -テストとドキュメンテーション

  • 再入門JavaScript - UnitTest
  • 再入門JavaScript -  Seleniumによる結合テスト
  • 再入門JavaScript -  JsDocによるドキュメンテーション

再入門JavaScript -パフォーマンス/高速化

  • 再入門JavaScript - プロファイリング
  • 再入門JavaScript - DOM描画フェーズ/タイマー
  • 再入門JavaScript - 事前コンパイルを利用した高速化
  • 再入門JavaScript - VMレベルでの動作を意識する
  • 再入門JavaScript - メモリリークとガーベジコレクタ
  • 再入門JavaScript - defer属性/script後置とminifier
  • 再入門JavaScript - 先読みと
  • 再入門JavaScript - Google Gears

再入門JavaScript -通信

  • 再入門JavaScript - クロスドメイン制約
  • 再入門JavaScript - 同一ドメイン通信
  • 再入門JavaScript - location.hashによるヒストリ管理
  • 再入門JavaScript - 通信の効率化とサーバサイド連携
  • 再入門JavaScript - クロスドメイン通信方法と注意点

再入門JavaScript - 名前空間篇

Wednesday, 29. October 2008 von hiroki_daichi

おこんばんわ。ひろきのだいちです。
今日は、再入門JavaScriptと題して、Perlなどのサーバサイドの言語になれている方に向けて、
JavaScriptにおける大規模開発の勘所として重要な名前空間の実現方法の解説と、
それらを簡単に提供するライブラリJS.Namespaceを作成しましたので、そのドキュメントを織り交ぜてご紹介します。

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

(more...)

再入門JavaScript - 動的ローディング

Wednesday, 29. October 2008 von hiroki_daichi

動的ロード

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

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. });

再入門JavaScript - 名前空間上の関数をExport

Wednesday, 29. October 2008 von hiroki_daichi

名前空間上の関数を利用する

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;みたいな記述は避けてください。