前回の記事「【MovableType】Twitterのつぶやきをサイドバーに表示する」で使ったソースコードを見ると、次のような不可思議な構文が含まれている。
/*@cc_on @if (@_win32 && @_jscript_version>4) var minmax_elements; (中略) minmax_scanner= window.setInterval(minmax_scan, minmax_SCANDELAY); window.attachEvent('onload', minmax_stop); @end @*/
この不思議な“@
”付きの構文は“条件付コンパイル”と呼ばれ、Javascript と JScript の間の数少ない差異の一つだ。これを使うとスクリプトを IE にだけ適用することができるので様々な方面で活用されている
@cc_on ってなに? – Clouder::Blogger
http://blog.clouder.jp/archives/001005.html一行で IE の JavaScript を高速化する方法 – IT戦記
http://d.hatena.ne.jp/amachang/20071010/1192012056JavaScriptでIEかどうかをたったの1行で判別する方法:phpspot開発日誌
http://phpspot.org/blog/archives/2007/04/javascriptie1.html
条件付コンパイルについて、以下を参考(コピペ)にしつつまとめてみる
Conditional Compilation of JScript/ JavaScript in IE
http://www.javascriptkit.com/javatutors/conditionalcompile.shtml
開始と終了
Javascript において、コメントは /* コメント */
のように記述する。
/* これはコメントです。 */
条件付コンパイルはこれを利用し、/*@cc_on ~ @*/
と記述する。IE 以外のブラウザでは単なるコメントにしか見えないようになっているわけだ。
/*@cc_on alert( "IE 使ってるね!" ); @*/
条件分岐
いわゆる if
文が使える。(元ネタ)
/*@cc_on @if ( @_jscript_version == 5.6 ) var nurupo = "インターネッツは任せろー"; alert( "やめて!" ); @elif ( @_jscript_version == 5.8 ) var nurupo = "……でもこれが IE8 だとしたら?"; alert( "ふしぎ!抱いて!" ); @else @*/ alert( "このスクリプトは IE6 と IE8 にしか反応しません" ); /*@end @*/
@if ~ @elif ~ @else ~ @end
の組み合わせで使う。elseif
でも elsif
でもないので注意。
特別な変数
上記のスクリプトで使った @_jscript_version
は IE(正確には JScript エンジン)によってあらかじめ定められた変数である。他にどんなものがあるか列挙してみる。
名前 | 意味 |
---|---|
@_win32 |
Win32 の時に true 。それ以外だと NaN 。 |
@_win16 |
Win16 の時に true 。それ以外だと NaN 。 |
@_mac |
Mac 版 IE だと true 。それ以外だと NaN 。 |
@_alpha |
DEC Alpha 版 IE だと true 。それ以外だと NaN 。 |
@_x86 |
CPU のアーキテクチャが x86 ファミリーなら true 。それ以外だと NaN 。 |
@_mc680x0 |
CPU のアーキテクチャが 680x0 ファミリーなら true 。それ以外だと NaN 。 |
@_PowerPC |
CPU のアーキテクチャが PowerPC ファミリーなら true 。それ以外だと NaN 。 |
@_jscript |
常に true 。 |
@_jscript_build |
JScript エンジンのビルドナンバー。 |
@_jscript_version |
JScript のバージョン。 |
@_debug |
デバッグモードなら true 。それ以外だと false 。 |
@_fast |
ファーストモードなら true 。それ以外だと false 。 |
最後の 2 つは JScript.NET で使うもののようだ。実質、必要なのはブラウザの判定に使う @_jscript_version
だけであろう。
値 | 対応するソフトウェア |
---|---|
1.0 |
Internet Explorer 3.0 |
2.0 |
Internet Information Server 3.0 |
3.0 |
Internet Explorer 4.0 |
3.0 |
Internet Information Server 4.0 |
4.0 |
Visual Studio 6.0 |
5.0 |
Internet Explorer 5.0 |
5.1 |
Windows 2000 |
5.1 |
Internet Explorer 5.01 |
5.5 |
Internet Explorer 5.5 |
5.6 |
Internet Explorer 6.0 |
5.6 |
Windows XP(SP2 まで) |
5.7 |
Internet Explorer 7.0 |
5.7 |
Windows XP SP3 |
5.7 |
Windows Vista |
5.8 |
Internet Explorer 8.0 |
5.8 |
Windows 7 |
なんだか IE 以外のも混じってるけど気にしない。IE9 では 5.9
になるのかな?
ユーザー定義変数
“@set @変数名 = 値
”の書式で自由に変数を定義することもできる。
/*@cc_on @set @myvar = @_jscript_version alert( "JScript エンジンのバージョンは " + @myvar + " です。" ); @*/
変数の比較には次の演算子が使える(優先順位順)。意味は Javascript のものと一緒だ。
! ~
* / %
+ -
<< >> >>>
< <= > >=
== != === !==
& ^ |
&& |
変数が未定義(NaN
)であるかどうかは次のようにして判断できる。
/*@cc_on @if ( @myvar != @myvar ) alert( "@myvar は NaN です!"); @end @*/
自分自身と等しくないのは NaN
だけなのだ。
応用編:XMLHttpRequest オブジェクトを得る
では、最後に実際の使用例を載せておく。Ajax に欠かせない XMLHttpRequest オブジェクト のインスタンスを作成するコードとしては、次のようなものが多く使われる。
function HttpRequest(url, parameters){ var pageRequest = false // XHR if ( window.XMLHttpRequest ) // 最近の IE や Firefox その他 pageRequest = new XMLHttpRequest() else if ( window.ActiveXObject ){ // 昔の IE try { pageRequest = new ActiveXObject( "Msxml2.XMLHTTP" ) } catch ( e ) { try { pageRequest = new ActiveXObject( "Microsoft.XMLHTTP" ) } catch ( e ) {} } } else return false }
この try ~ catch 構文は IE4 で使えないためにエラーになってしまう。未だに IE4 を使っている人がいるかどうかは別にして、Javascript を使えるすべてのブラウザに対応可能なものを条件付コンパイルによって書くと次のようになるだろう。
function HttpRequest(url, parameters){ var pageRequest = false // XHR /*@cc_on @if ( @_jscript_version >= 5 ) try { pageRequest = new ActiveXObject( "Msxml2.XMLHTTP" ) } catch ( e ) { try { pageRequest = new ActiveXObject( "Microsoft.XMLHTTP" ) } catch ( e2 ) { pageRequest = false } } @end @*/ if ( !pageRequest && typeof XMLHttpRequest != 'undefined' ) pageRequest = new XMLHttpRequest()