Prototype.js バージョン1.7公開に合わせ小技紹介その1
var browser1 = (function() { var ua = navigator.userAgent; var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; return { IE: !!window.attachEvent && !isOpera, Opera: isOpera, WebKit: ua.indexOf('AppleWebKit/') > -1, Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, MobileSafari: /Apple.*Mobile/.test(ua) } })(); //browser1はオブジェクトなのでそのままドットシンタックスでブラウザを指定すればいい。 alert( browser1.IE );ひとつはグローバル名前空間を汚さないという点があります。クロージャというJavaScriptの特性を利用しています。これはよくつかわれるテクニックです。それでは、クロージャを使わないとどうなるか。下に示すように関数を使わない方法で同じようにブラウザ判定をしてみると……
var ua = navigator.userAgent; var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; var browser2 = { IE: !!window.attachEvent && !isOpera, Opera: isOpera, WebKit: ua.indexOf('AppleWebKit/') > -1, Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, MobileSafari: /Apple.*Mobile/.test(ua) }; alert( browser2.IE );ブラウザ判定にbrowser2の他にua、isOperaというグローバル変数が使われているため、グローバル名前空間を汚染する可能性が高まってしまいます。JavaScriptではライブラリ同士の衝突がよく問題になるので重大なバグにつながる恐れがあります。 もうひとつの利点は、関数呼び出し時の処理を軽くするというのがあります。次の例を見てみます。これは単純に元のコードから()を取り去ったものです。
var browser3 = function() { var ua = navigator.userAgent; var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; return { IE: !!window.attachEvent && !isOpera, Opera: isOpera, WebKit: ua.indexOf('AppleWebKit/') > -1, Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, MobileSafari: /Apple.*Mobile/.test(ua) } }; //browser3はメソッドなので一度呼び出した上で、ドットシンタックスでブラウザを指定する必要がある。しかし、これだとブラウザを確認するたびにいちいちメソッドを呼び出すことになる。 alert( browser3().IE );ブラウザ判定を関数(メソッド)にすると、内部でローカル変数を参照するのでグローバル名前空間の汚染は避けられるものの、ブラウザを調べたいときにいちいち関数を呼び出さなければならなくなります。こうしたことから、browser1のように関数を()でくくってその場で実行するのが、処理の速さと汚染対策を両立する最良の方法となるわけです。 しばらくPrototype.jsを読解しながらここで使われるテクノロジーの紹介を続けてみたいと思います。