仮引数とクロージャ ― 2007年05月04日 02時58分41秒
(元記事:あるSEのつぶやき: prototype.jsでプライベートメソッドを持つクラスを作る方法)
ローカル変数の代わりに
個人的には最近まったく使わなくなっていた「JavaScriptによるプライベートフィールドの隠蔽」だが、あるSEのつぶやきさんが取り上げていたので一言(でもないか)。
リンク先記事で、Animal#defineメソッド内の実装で、プライベートフィールドをわざわざ定義しているが、これって、defineメソッドの仮引数「_sex」を_getSexで囲っちゃっても同じなんだよね。
15: define : function(_sex) {
16: //プライベートフィールド
17:// var sex = _sex; // ←コメントアウト
18:
19: //プライベートメソッド
20: var _getSex = function() {
21: return _sex;// ←変更。仮引数にアクセスできるし。
22: }
23:
24: //Privileged(特権)メソッド
25: this.getSex = function (){
26: return Animal.SEXTYPE[_getSex()];
27: }
28: }
仮引数も、関数内でvar宣言されたローカル変数も、このメソッド内の実行コンテキストにバインドされた変数オブジェクトのプロパティであることには変わりがないので、宣言するだけ冗長かと。
同じIdentifierの仮引数とローカル変数の関係を見るために以下のコードを検証してみた。
function test1() {
var a;
return "test1: " + a;
}
function test2(a) {
return "test2: " + a;
}
function test3(a) {
var a;
return "test3: " + a;
}
alert( test1("hoge") ); // 'test1: undefined'
alert( test2("hoge") ); // 'test2: hoge'
alert( test3("hoge") ); // 'test3: hoge'
Firefox1.5でしか試していないが、たぶんどの処理系でも同じだと思う。ポイントはtest2とtest3の結果が同じになること。
ついでだが、test3内でローカル変数宣言に代入式を与えると、当然仮引数「a」はオーバーライドされるので、違う結果になる。
おまけ
この手の解説で、以前は「Effective JavaScript」というよいコンテンツがあったのだが、現在は公開されていない。非常に残念だ。
現在はアクセスしても404になるのでリンクはせず、当時のURLを掲載しておく。www.archive.orgなんかを利用するとまだ確認できるかも。
EXEを作ってみた ― 2007年05月04日 03時11分17秒
これはちょっと便利かも
ゆるゆるとJSDBを試しているが、本家のチュートリアル眺めてたら、「Standalone JSDB programs」という項があって、
c:\temp>pkzip program.zip main.jsとか書いてあるじゃないですか。
c:\temp>copy /b jsdb.exe+file.zip program.exe
c:\temp>program.exe
さらに-helpオプションつけて起動してみたら、.zipのアーカイブをパラメータに渡せるとあった。
D:\jsdb>jsdb -help JSDB 1.52Compiled Apr 27 2007. http://www.jsdb.org/ Copyright 2003-2006 by Shanti Rao and others. JSDB [-strict] [-werror] [-load file.js] [-debug server] [lib.zip] [program.js] -strict Strict syntax mode -werror Treat warnings as errors -load file.js Load and run file.js before program.js -debug server:port Connect to a debugger serverということは、「main.js」にメインコードを記述し、それをzipで固めて、チュートリアルにあるように結合コピーするとオリジナルのコンソールアプリケーションが作れるってことじゃない!こいつぁ便利かも。lib.zip Set lib.zip as the default location for library files Executes main.js if found in the zip fileprogram.js Runs a JavaScript program. If omitted, enter console mode D:\jsdb>
早速試してみた
まず、以下のコードを「main.js」で保存。コードの中身はかなり適当。
write("what your name ? > ");
writeln( "hello, ", readln()," !!" );
sleep( 1000 );
そんで、main.jsをmain.zipとして固める。
そしてチュートリアルにある要領で、コピー。hello.exeとした。
D:\jsdb>copy /b jsdb.exe+main.zip hello.exe
jsdb.exe
main.zip
1 個のファイルをコピーしました。
D:\jsdb>
さて、hello.exeを実行。
D:\jsdb>hello what your name ? > hoge hello, hoge !! D:\jsdb>おお、ちゃんとできてるよ。
使い道
とりあえず思いつくのは、ライブラリ読み込み処理をmain.jsに記述してカスタマイズした実行環境にするってとこかな。
と思ったが、アーカイブ内のmain.jsを実行するとそのまま終了しちゃうので、この方法だとドラッグドロップ専用になっちゃうな(たぶんコマンドライン引数は受け取れるだろうから)。 もっとも、ライブラリロードを起動時になんとかするんだったら、-loadをくっつけたバッチファイルにしちゃえばよいんだし。ちぇ。

最近のコメント