アンケートご協力のお願いgihyo.jpでは,2010年度に向けて豪華プレゼントが当たる読者属性アンケートを実施しております。ご協力ください。

gihyo.jp » DEVELOPER STAGE » 特集 » prototype.jsを読み解く » 第5回 Prototypeライブラリ(1290~1608行目)

prototype.jsを読み解く

第5回 Prototypeライブラリ(1290~1608行目)

遠いリポジトリに便利なsvk

第五回目です。

Subversionのlogやdiff,annotateサブコマンドを駆使するといろいろな情報が取れることは前回紹介しました。

ただ,Railsのような海外にある,また人気があって負荷が高いことも多いリポジトリに対して,頻繁にそれらのサブコマンドを使っても,結果が出てくるまで遅いことが多々あり快適に解析が進められません。

そんな時にはsvk を使う手があります。

svkのmirrorサブコマンドを使うと,ローカルのディスク上に,Subversionリポジトリの特定部分以下だけをまるごとミラーすることができます。今回のような状況では,http://svn.rubyonrails.org/rails/spinoffs/prototype/だけでもローカルにミラーしておくと,作業が格段に快適になります。

% svk mirror http://svn.rubyonrails.org/rails/spinoffs/prototype //prototype
Committed revision 3764.
% svk sync //prototype
Retrieving log information from 1 to 7693
Committed revision 3765 from revision 3362.
... (ここで途中で失敗する場合は再度 svk sync)
% svk checkout //prototype prototype
...
% cd prototype/tags/rel_1-5-1-1/src
% svk log dom.js | less

という手順で利用できます。

では,今回はElementへの拡張からです。Elementまわりは膨大なので,次回も含めて2分割でお送りします。

Element への拡張

1290: if (!window.Element) var Element = {};
1291: 

まず,必要に応じて空のElementオブジェクトをプレースホルダとして用意します。

1292: Element.extend = function(element) {
1293:   var F = Prototype.BrowserFeatures;
1294:   if (!element || !element.tagName || element.nodeType == 3 ||
1295:    element._extended || F.SpecificElementExtensions || element == window)
1296:     return element;
1297: 
1298:   var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
1299:    T = Element.Methods.ByTag;
1300: 
1301:   // extend methods for all tags (Safari doesn't need this)
1302:   if (!F.ElementExtensions) {
1303:     Object.extend(methods, Element.Methods),
1304:     Object.extend(methods, Element.Methods.Simulated);
1305:   }
1306: 
1307:   // extend methods for specific tags
1308:   if (T[tagName]) Object.extend(methods, T[tagName]);
1309: 
1310:   for (var property in methods) {
1311:     var value = methods[property];
1312:     if (typeof value == 'function' && !(property in element))
1313:       element[property] = cache.findOrStore(value);
1314:   }
1315: 
1316:   element._extended = Prototype.emptyFunction;
1317:   return element;
1318: };
1319: 

まずはElement.extend()関数です。これは既存の要素に,Prototypeライブラリ独自のメソッド群を付け加えるものです。

昔はElement以下の追加メソッドは,Element.visible(targetElement)のように呼び出すようになっていましたが,現在では各要素自体のメソッドとしてtargetElement.visible()のように呼び出すことができるようになっています。

できるだけ効率的に,かつ副作用を抑えつつ便利にするために,このElementに対するメソッド追加はかなりややこしいことになっています。

1294行目からは,メソッドを付け加える必要があるかどうかを判断しています。以下の条件のどれかに該当するとreturn elementで何もせずに返ります。

条件文 付け加える必要がない理由
!element そもそも引数elementが無効,null,undefinedなど
!element.tagName tagNameプロパティが無いので要素ではない
element.nodeType == 3 テキストノード(3)は対象外
element._extended すでにこの関数により拡張済み
F.SpecificElementExtensions コード最後部のElement.addMethods()の呼び出しにより,HTMLElement.prototype以下にメソッドを追加してあるので,個々の要素インスタンスに対して追加する必要は無し
element == window windowは対象外。それ以前にtagNameのチェックで除外されているはず

1298行目では,ここで使う変数や,ショートカット関数などを定義しています。

1301行目からは,このブラウザで拡張するべき関数オブジェクトをmethodsオブジェクトに詰め込んでいます。ここでmethodsのプロパティ名が要素に拡張されるメソッド名で,プロパティ値が関数オブジェクトになります。

グローバルなHTMLElementが定義されている場合,F.ElementExtensionsが真となります。この値はIEでは偽ですがFirefox,Safari,Operaでは真になります。真の場合はHTMLElementに定義されているメソッドが使えるのでここで拡張する必要がなくなります。

Element.Methods.ByTagには,タグ毎に拡張するべき関数が入っているので,今回渡された要素のタグ名に対して該当するものがあればそれもmethodsオブジェクトに加えます。

あとは,methodsに入っている値を列挙して,プロパティ値がちゃんと関数オブジェクトで,かつまだelementには該当する名前のプロパティがセットされていない場合に,Element.extend.cache.findOrStore()関数を使って拡張しています。

最後に,element._extendedに「拡張済み」の印を入れて,elementを返します。

1320: Element.extend.cache = {
1321:   findOrStore: function(value) {
1322:     return this[value] = this[value] || function() {
1323:       return value.apply(null, [this].concat($A(arguments)));
1324:     }
1325:   }
1326: };
1327: 

1320行目からはElement.extend.cacheです。findOrStore()関数だけがプロパティとして定義されています。

findOrStore()関数は,先ほどのElement.extend()で,関数オブジェクトを渡して呼び出されています。1313行目において,cache.findOrStore()の形で呼び出されているので,この関数におけるthis はcacheすなわちElement.extend.cacheとなります。

return this[value] = this[value] || function(){...} という形は,Element.extend.cache オブジェクトのプロパティ名(といっても文字列ではなく関数オブジェクトがキーになっていますが)にあればそれを返し再度代入,無ければ関数を定義して代入,そしてその代入された値を返す,というものです。これにより,同じ無名関数がいくつも定義されないようにしています。

無名関数の中では,valueとして渡された関数オブジェクトに対してapply()を呼び出しています。例えば1329行目からのElement.Methods.visibleがvalueとして渡されているとすると,apply()の第一引数がnullなので,visible()の中でのthisはグローバルオブジェクトとなります。第二引数に[this].concat($A(arguments))を渡していますが,ここのthisは無名関数のコンテキストでのthisなので,通常はElementインスタンスになります。例えばIDが't1'という要素があれば,$('t1').visible()として呼び出すのでvisible の左側すなわち $('t1') が this となります。 arguments もこの無名関数のコンテキストなので,$('t1').visible(1,2,3) と書けば arguments に [1,2,3] が入ります。これらを concat() で繋いで apply() に渡しているので,visible() 関数の定義では,最初の引数として Element インスタンスを受け取る形になります。

  • ECMA-262 第三版 - 15.3.4.3 Function.prototype.apply (thisArg, argArray)

著者プロフィール

栗山淳(くりやまじゅん)

S2ファクトリー株式会社株式会社イメージソース所属。
本業はWeb制作会社の裏方。得意分野はFreeBSDやPerlのはずだが,必要に迫られるとHTML/CSSやJavaScriptも書く。

コメント

コメントの記入

パスサポ

多数の情報処理技術者試験対策書籍の発行実績を誇る技術評論社がお届けする,資格試験合格サイト「めざせ! 情報処理試験 パスサポ」が開設されました。

ピックアップ

サクセスストーリーに続く,快適サーバー運用管理のヒント!

データの増大,煩雑な管理,システムダウン,セキュリティなど,迫りくる課題からシステム管理者の負担を軽くするポイントを解説します。

gihyo.jp インフラエンジニア情報局

ネットワークやITにかかわるあらゆる業種で必要とされるインフラエンジニアに向けた技術情報や心構え,その魅力について多角的に紹介。

テストエンジニア ステーション

いま,ITに関わるあらゆる開発業務で注目されつつあるテスト系エンジニアをターゲットにしたコンテンツサイトを展開します。

一行クイックアンケート

gihyo.jpで取り上げてほしいネタは?

※検索はページ右上の検索ボックスをご利用ください。

その他の連載

使ってみよう! Windows Live SDK/API

Windows Liveサービスの一部にはAPIやSDKとして提供されているものがあります。本連載では各API・SDKの紹介とそれらを利用したアプリケーションを開発していきます。

Lifelog~毎日保存したログから見えてくる個性

コンピュータを使って,日常のさまざまなことの記録(ログ)をとり,それを分析して活用することで,もう一段階上の「楽な生活」をめざす日々の研究報告です。

もっと便利に!jQueryでラクラクサイト制作(実践サンプル付き)

本連載では,実践サンプルとともに,jQueryを上手に活用してサイト制作の品質向上・効率化を実現するための実践テクニックを解説します。

Ruby Freaks Lounge

Rubyに関わる,執筆者自身の旬なテーマを扱った,リレー形式の連載です。

これでできる! クロスブラウザJavaScript入門

JavaScriptはウェブ制作において避けては通れない重要な言語ですが,JavaScriptに苦手意識を持たれている方は少なくないようです。 その最大の原因がクロスブラウザ対応という課題であり,本連載ではクロスブラウザ対応のテクニックを詳細に解説します。

ビジネスで成功するためのシステム運用管理のポイント

システムの多様化,技術進歩に伴い,ITシステムの運用管理の必要性が年々高まっています。本連載では,システムの運用管理とは何かについて,現場のニーズと具体的な指針を押さえながらを解説します。

2010年版SEO体得講座

本連載では,いまや企業サイトの戦略の1つとして欠かすことのできないSEOについて,最新トレンドからすぐに使えるTipsまでを紹介します。

小型Linuxサーバの最高峰 OpenBlockS 600活用指南

搭載メモリの増加,CPUクロックの向上など,あらゆる面が強化された期待の新モデルOpenBlockS 600。この記事ではOpenBlockS 600の紹介から,活用するためのさまざまなノウハウを紹介していきます。

連載一覧

gihyo.jp

  • DEVELOPER STAGE
  • ADMINISTRATOR STAGE
  • WEB+DESIGN STAGE
  • LIFESTYLE STAGE
  • SCIENCE STAGE
  • NEWS & REPORT

書籍案内

  • 新刊書籍
  • 書籍ジャンル一覧
  • 書籍シリーズ一覧
  • 新刊ピックアップ
  • ロングセラー
  • 電脳会議

定期刊行物一覧

  • Software Design
  • WEB+DB PRESS
  • Web Site Expert
  • 組込みプレス

最近のコメント