March 2009
Volume 24 Number 03
Cutting Edge: jQuery によるリッチなクライアント スクリプトについて (第 1 部)
Dino Esposito | March 2009
目次
jQuery オブジェクト
セレクタ
フィルタ
フォーム フィルタ
ラップされたセットの操作
jQuery のチェーン機能
HTML を理解する
言うまでもないことですが、Web ブラウザからより多くの機能を引き出すには、より多くの JavaScript コードを記述する必要があります。HTML ページで実行できる動作を増やすために 1995 年頃登場した JavaScript 言語は、明確に開発者向けにデザインされたものではありませんでした。実際には、HTML 要素の操作、スタイルの設定、およびユーザー入力への応答の手段として用意されたものです。また、クライアント側での入力の検証や、その他の軽量な操作にも幅広く使われています。
JavaScript は、このようなややありふれた用途に使用されてきたため、記述も容易であると思われるかもしれません。しかし、MSDN Magazine 2007 年 5 月号の「オブジェクト指向の手法によって高度な Web アプリケーションを作成する」で Ray Djajadinata が述べているように、優れた JavaScript コードを書くことはそう単純ではない一方で、十分に理解すれば、さらに高度な機能を引き出すことも可能です。
ただし、JavaScript の欠点の 1 つとして、インタープリタ型 (コンパイラ型でなく) 言語であるため、ブラウザによる解釈に左右されるということがあります。同じ JavaScript コードをすべてのブラウザが同じように処理するわけではありません。しかし、jQuery のようなライブラリを使用することで、ブラウザが異なっても JavaScript コードの動作をかなり予測できるようになります。
マイクロソフトでは現在、jQuery を完全にサポートし、ASP.NET Model-View Controller (MVC) フレームワークと共に jQuery を配布しています。さらに、jQuery IntelliSense を Visual Studio 2008 SP1 に完全に統合するための拡張機能も開発しました。
今月の記事では、jQuery ライブラリの主な特徴について説明し、特に、CSS セレクタ、関数のチェーン機能、およびラップされたセットに焦点を合わせます。次回以降は、jQuery を使ってイベントや効果を処理する方法や、ブラウザ側のキャッシュ、AJAX 要求など、より具体的なトピックを取り上げていきます。
jQuery の概要
jQuery を使用すると、よりすばやく簡単に JavaScript のコードを記述できるようになります。このライブラリには、開発者の不満を減らしながら生産性を劇的に向上させる、さまざまなヘルパ関数が用意されています。それらを用いて記述したコードは、高い抽象レベルによって複数のチェックやエラー処理手順が隠されているため、読みやすく、堅牢性も向上します。
John Resig によって記述されたこのライブラリは、1 つの .js ファイルから構成され、このファイルは docs.jquery.com/Downloading_jQuery からダウンロードできます。最新バージョンは 1.2.6 で、2008 年春にリリースされました。ダウンロード サイトでは、非圧縮、パック、最小化の 3 種類のバージョンが用意されています。
非圧縮バージョンはサイズが約 100 KB で、完全に人間が判読できる形式になっており、コメントも付けられています。これは、熟読してデバッグするためのバージョンとして最適です。
最小化バージョンのサイズは約 50 KB です。機能の実装に厳密には必要でない追加文字がすべてソース コードから削除されています。これは人間が読むのが不可能とは言わないまでも実用的ではなく、あくまでコンピュータのためのバージョンです。
最後に、パック バージョンはサイズがわずか 30 KB ですが、クライアントでの初期化に時間がかかります。jQuery の公式サイトでは、実稼動環境用にはパック バージョンの代わりに最小化バージョンを使用することを推奨しています。また、ネットワーク上では GZip 圧縮が標準手段であり、今日のすべての Web サーバーおよびブラウザが対応していることを考慮してください。GZip 圧縮では、サイズが約 20 KB に縮小されます。GZip を使用すれば、パック バージョンをダウンロードする意味はほとんどなくなります。
ASP.NET プロジェクトでは、IntelliSense を有効にするための jquery-1.2.6-vsdoc.js と jQuery IntelliSense を完全にサポートするための Visual Studio 2008 更新プログラム (「KB958502 - '-vsdoc.js' IntelliSense ドキュメント ファイルに対する JScript エディタ サポート」を参照) も必要となります。
ASP.NET では、単純な <script> タグを使用してライブラリにリンクするか、または ScriptManager コントロールの Scripts セクションに次のように記述できます。
<asp:ScriptManager id="ScriptManager1" runat="server"> <Scripts> <asp:ScriptReference path="Scripts/jquery-1.2.6.min.js" /> </Scripts> </asp:ScriptManager>
このアプローチは、Microsoft AJAX ライブラリをページに埋め込む場合を除き、現在のバージョンの ASP.NET では推奨されないことに注意してください。ASP.NET 4.0 では、Microsoft AJAX クライアント フレームワーク ファイルの取り込みを無効にできるようになるため、このアプローチも適切な選択肢となります。
jQuery の機能セット全体は、4 つの主な領域に分けられます。DOM のクエリと操作、効果とアニメーション、AJAX、およびコア機能です。コア機能は、配列の使用、データのフィルタ処理、およびブラウザ機能の検出に使用されます。
jQuery オブジェクト
ライブラリの名前に含まれる "query" という語が、すべてを物語っています。これは、ページの DOM に対してクエリを実行することを意味し、jQuery がまさにその力を発揮する部分でもあります。
ライブラリでは、DOM 要素を選択するための強力なインターフェイスが提供され、これは単に特定の ID に一致する要素を検索するだけでなく、はるかに進んだ操作ができます。たとえば、特定の CSS クラスを共有する要素、特定の属性を持つ要素、ツリー内で特定の位置に表示される要素、または他の要素と関係を持つ要素などを、すべて簡単に選択できます。さらに重要なこととして、SQL でのデータのクエリと同様に、フィルタ条件を追加したり、これらすべてのクエリ機能を連結したりできます。
jQuery ライブラリのルートは jQuery 関数であり、次のように定義されています。
var jQuery = window.jQuery = window.$ = function( selector, context ) { return new jQuery.fn.init( selector, context ); };
$ 関数は、jQuery 関数のエイリアスです。jQuery オブジェクトを作成するときには、セレクタとコンテキストを渡します。セレクタはクエリ式を示します。コンテキストは、クエリを実行する DOM の場所を示します。コンテキストが指定されない場合、jQuery 関数はページ DOM 全体の中から DOM 要素を探します。
jQuery 関数 (その $ エイリアスも同様) は、渡された引数に対して処理を行い、クエリを実行してから、結果を含む新しい jQuery オブジェクトを返します。新しく作成された jQuery オブジェクトに対して、新しいステートメント内およびステートメントのチェーン内で、さらにクエリを実行したり、フィルタを適用したりできます。
ルート jQuery オブジェクトは、次のシグネチャをサポートしています。
jQuery( expression, [context] ) jQuery( html, [ownerDocument] ) jQuery( elements ) jQuery( callback )
最初のシグネチャは、CSS セレクタを受け取り、HTML 要素のラップされた配列を返します。これは、ラップされたセットと呼ばれます。2 番目のシグネチャは、HTML 文字列を受け取り、関連するサブツリーを作成して、指定された所有元ドキュメントがある場合にはそのドキュメントに追加します。3 番目のオーバーロードは、指定された DOM 要素を取得します。最後に、4 番目のシグネチャは、単にコールバック関数を受け取り、ページのドキュメントが完全に読み込まれるとすぐに、ドキュメント全体に対してその関数を実行します。
また、ルート jQuery オブジェクトには、図 1 に示すようないくつかのヘルパ メソッドがあります。開発者にとって特に興味深いと思われるのは each メソッドであり、これは jQuery オブジェクトの内容 (通常は CSS セレクタによって選択された DOM 要素) に対する手動の繰り返しの手間を省くために使用できます。each メソッドの動作を示すコード例を次に示します。このループは、フォーム内のすべての <input> タグを処理します。
$("form input").each( function(i) { this.title = "Input #" + i; } );
図 1 jQuery オブジェクトのヘルパ メソッド |
メソッド | 説明 |
each( callback ) | ラップされたセットの内容に対してループ処理を行い、指定されたコールバック関数を実行します。 |
length | ラップされたセット内の要素数を返すプロパティです。 |
eq( position ) | ラップされたセットを、指定した位置の 1 つの要素に縮小します。 |
get() | ラップされたセットの内容を DOM 要素の配列として返します。 |
get( index ) | ラップされたセット内の指定した位置の DOM 要素を返します。 |
index( element ) | ラップされたセット内の指定した DOM 要素の 0 から始まるインデックスを返します (要素が存在する場合)。 |
each() と手動の JavaScript ループとの違いは、each() は自動的に "this" オブジェクトを、処理中のコレクション内の要素にマップすることです。ただし、コールバック関数は、繰り返しの (0 から始まる) インデックスである整数パラメータをオプションとして受け取ります。jQuery のセレクタおよび CSS ベースの構文について、さらに詳しく見てゆきましょう。
$ 関数の最も簡単な使用法を次に示します。
var elem = $("#grid");
このコード例の $ 関数は、指定した式に一致する ID プロパティを持つすべての DOM 要素を返します。# 記号は ID 文字列の一部ではなく、$ 関数が ID 文字列、CSS クラス、および HTML タグ名を明確に区別するためのプレフィックスです (# 記号は、ID を選択する標準的な CSS 構文の一部です)。上のコード例は、機能的には次の DOM ステートメントと等価です。
var elem = document.getElementById("grid");
HTML DOM では、ASP.NET の場合とは異なり、複数の要素が同じ ID を共有できることに注意してください。いくつかの要素が ID と一致した場合、getElementById は、最初に一致した要素だけを返します。一方、getElementsByName は、コレクション全体を返します。
古典的な DOM メソッドと $ 関数が似ているのはそこまでです。$ の能力は、はるかに進んでいます。$ を使用すれば、DOM 要素を選択した後、それぞれの要素に関数を適用できます。
セレクタ式は CSS 3.0 構文に基づきながら、かなり複雑なレベルの記述ができます。図 2 に、サポートされるセレクタの一覧を示しています。この一覧にはフィルタが含まれていませんが、それについては後で取り上げます。セレクタの階層では、祖先、親、および前の要素を、単なる HTML 要素ではなく、任意の有効なセレクタとすることが可能です。図 3 に、いくつかのサンプル クエリを示します。
図 2 サポートされる jQuery セレクタ |
セレクタ | 説明 |
#id | DOM 内で一致する ID 属性を持つ最初の要素を返します (存在する場合)。 |
element | 一致するタグ名を持つすべての要素を返します。 |
.class | 一致する CSS クラスを持つすべての要素を返します。 |
* | ページ内のすべての要素を返します。 |
selector1, ..., selectorN | 指定された基本的なセレクタをすべて適用し、それらの組み合わせによる結果を返します。 |
ancestor descendant | 指定された ancestor セレクタに対して、descendant セレクタに一致するすべての子孫要素のコレクションを返します。たとえば、"div p" と指定すると、<div> 内のすべての <p> 要素が返されます。 |
parent > child | 指定されたセレクタに対して、child セレクタに一致するすべての子要素のコレクションを返します。 |
prev + next | 指定されたセレクタに対して、next セレクタに一致し、prev セレクタの次であるすべての兄弟要素のコレクションを返します。 |
prev ~ sibling | 指定されたセレクタに対して、sibling セレクタに一致し、prev セレクタの次であるすべての兄弟要素のコレクションを返します。 |
図 3 jQuery セレクタの動作例 |
セレクタ例 | 効果 |
form input | ページ内の <form> タグに含まれる入力フィールドをすべて返します。 |
#Form1 input | Form1 という名前のフォームに含まれる入力フィールドをすべて返します。 |
h2 + p | 同じ親の子である <h2> の次に来るすべての <p> タグを返します。 |
input.textBox | CSS クラスが "textBox" であるすべての <input> タグを返します。 |
div span.myClass | CSS クラスが "myClass" である、<div> 内の <span> タグをすべて返します。 |
セレクタは、属性、内容、位置、および表示に関してフィルタを適用することにより、選択条件をさらに細かく指定できます。図 4 に、jQuery の一般的なフィルタをいくつか示します。全フィルタの一覧は、docs.jquery.com/Selectors にあります。
first や last などのフィルタは、返されたコレクション内で特定の位置にある DOM 要素を見つけます。また、インデックスに基づいた構文を使用して、要素に eq、gt、および lt フィルタを適用することもできます。フィルタ eq は、指定されたインデックスと一致するインデックスを持つ要素を取得します。gt は指定されたインデックスより大きい要素を取得し、lt は指定されたインデックスより小さい要素を取得します。
属性フィルタは、指定された属性が特定の値と指定された関係を持つような HTML 要素を選択する強力なツールです。図 4 には、最も一般的に使用される属性フィルタだけを示しています。他にも、指定された属性が特定の値で始まる要素、特定の値で終わる要素、特定の値を含む要素などを選択するフィルタがあります。必要な構文を次に示します。
[attribute^=value] // begins with value [attribute$=value] // ends with value [attribute*=value] // contains value
図 4 jQuery フィルタ |
位置フィルタ | 説明 |
:first | 選択された要素コレクションの最初の要素を返します。 |
:last | 選択された要素コレクションの最後の要素を返します。 |
:not(selector) | 指定されたセレクタに一致する要素をすべて除外します。 |
:even | 選択されたコレクション内の偶数の要素をすべて返します。 |
:odd | 選択されたコレクション内の奇数の要素をすべて返します。 |
子フィルタ | 説明 |
:nth-child(expr) | 指定された式に一致する親のすべての子要素を返します。式にはインデックスまたは数式 (3n+1 など) を指定でき、odd や even などの標準文字列も使用できます。 |
:first:child | 親の最初の子である要素をすべて返します。 |
:last-child | 親の最後の子である要素をすべて返します。 |
:only-child | 親の唯一の子である要素をすべて返します。 |
コンテンツ フィルタ | 説明 |
:contains(text) | 指定されたテキストを含む要素をすべて返します。 |
:empty | 子を持たない要素をすべて返します (テキストは子ノードと見なされます)。 |
:has(selector) | 指定されたセレクタに一致する要素を 1 つ以上含む要素をすべて返します。 |
:parent | 1 つ以上の子を持つ要素をすべて返します (テキストは子ノードと見なされます)。 |
表示フィルタ | 説明 |
:hidden | 現在非表示になっている要素をすべて返します。type 属性が "hidden" である入力要素がリストに追加されます。 |
:visible | 現在表示されている要素をすべて返します。 |
属性フィルタ | 説明 |
[attribute] | 指定された属性を持つ要素をすべて返します。 |
[attribute = value] | 指定された属性が指定された値に設定されている要素をすべて返します。 |
[attribute != value] | 指定された属性 (存在する場合) が指定された値と異なる要素をすべて返します。 |
属性フィルタは、次のように複数のフィルタを単純に並べることで連結できます。
[align=right][valign=top]
特に強力なフィルタが nth-child です。これは、次に示すように、いくつかの異なる入力式をサポートします。
:nth-child(index) :nth-child(even) :nth-child(odd) :nth-child(sequence)
最初の形式は、ソース セレクタ内の HTML 要素の n 番目の子を選択します (n は指定されたインデックス)。odd または even フィルタを指定すると、奇数または偶数の位置 (0 から開始) にあるすべての要素が返されます。最後の例では、nth-child を数式 (3 の倍数を示す 3n など) のルート式として渡すことができます。
例として、次に示すセレクタは、DataGrid1 というテーブルの中で、数式 3n+1 によって決定される位置 (0 から始まるインデックスなので 1、4、7、...) にあるすべての行を返します。
#DataGrid1 tr:nth-child(3n+1)
次の例はずっと複雑な式であり、jQuery セレクタの優れた能力と柔軟性を示しています。
#DataGrid1 tr:nth-child(3n+1):has(td[align=right]) td:odd
これは次のような意味です。前の手順で選択されたテーブルの行すべて (位置 1、4、7、...) の中で、属性 align の値が "right" に等しいセル (<td> タグ) を含む行だけが取り出されます。さらに、残った行の中で、奇数のインデックスを持つ列のセルだけが選択されます。図 5 の HTML テーブルを考えてみましょう。図 6 で、黄色い背景のセルがクエリの結果です。
図 5 HTML テーブル
<table id="DataGrid1" border="1"> <tr> <td>Column1</td> <td>Column2</td></tr> <tr> <td>Val1</td> <td align="right">Num1</td></tr> <tr> <td>Val2</td> <td align="right">Num2</td></tr> <tr> <td>Val3</td> <td align="right">Num3</td></tr> <tr> <td>Val4</td> <td>Num4</td></tr> <tr> <td>Val5</td> <td>Num5</td></tr> <tr> <td>Val6</td> <td>Num6</td></tr> <tr> <td>Val7</td> <td>Num7</td></tr> </table>
図 6 テーブルの特定のセルを選択する
フォーム フィルタ
前述のとおり、jQuery セレクタの全体的な構文は、CSS 3.0 セレクタの構文と似ており、図 7 に示すような追加の擬似要素によって拡張されているだけです。
特に、:input フィルタは、<input> タグに限らず、ページに含まれる可能性のあるすべての論理入力要素に適用されます。実際、リストボックスやドロップダウン リストの表示に使用される <textarea> 要素および <select> 要素も含まれます。図 7 に示すセレクタは、CSS セレクタとは一致しませんが、特定の型のすべての入力タグなど、類似した要素を簡単に選択する手段を提供します。たとえば、:text セレクタは、次の構文と機能的に等価です。
form input[type=text]
図 7 フォーム フィルタ |
セレクタ | 説明 |
:input | textarea やドロップダウン リストも含め、入力データを収集する役割を持つ要素をすべて返します。 |
:text | type 属性が text である入力要素をすべて返します。 |
:password | type 属性が password である入力要素をすべて返します。 |
:checkbox | type 属性が checkbox である入力要素をすべて返します。 |
:radio | type 属性が radio である入力要素をすべて返します。 |
:submit | type 属性が submit である入力要素をすべて返します。 |
:reset | type 属性が reset である入力要素をすべて返します。 |
:image | type 属性が image である入力要素をすべて返します。 |
:button | type 属性が button である入力要素をすべて返します。 |
:file | type 属性が file である入力要素をすべて返します。 |
:hidden | type 属性が hidden である入力要素をすべて返します。 |
:enabled | 現在有効になっている入力要素をすべて返します。 |
:disabled | 現在無効になっている入力要素をすべて返します。 |
:checked | 現在オンになっている checkbox 要素または radio 要素をすべて返します。 |
:selected | 現在選択されているリスト要素をすべて返します。 |
ページ内で有効または無効になっているすべての入力要素を取得したり、オンになっているすべてのチェックボックスやオプション ボタン、および現在選択されているリスト項目を取得したりする、便利なヘルパが他にもあります。
ラップされたセットの操作
セレクタに一致する HTML 要素は、jQuery オブジェクトの新しいインスタンスにパックされて返されます。このオブジェクトには、すべての DOM 参照を含む JavaScript 配列が格納されます。この結果は、一般に "ラップされたセット" と呼ばれます。ラップされたセットは、一致する要素が見つからなかった場合でも null にはなりません。この状況は、次のように jQuery オブジェクトの length プロパティで確認できます。
// All TDs with a child IMG var w_set = new jQuery("#DataGrid1 td:has(img))"); if (w_set.length == 0) alert("No match found."); else alert(w_set.length)
jQuery によって示される高いレベルの柔軟性は強力な機能ですが、目的の要素をすべて取得した後は、それらを処理する必要があります。考えられる最も単純なアプローチとしては、次に示すように、ループを設定し、コレクション内の各アイテムに対して関数を実行します。
var ws = $("#DataGrid1 tr:nth-child(3n+1)"); for(i = 0; i<ws.length; i++) { processElement(ws[i]); } function processElement(elem) { ... }
このような手動の繰り返しでは、古典的な JavaScript プログラミングと同様に、DOM 要素に直接アクセスします。
jQuery ライブラリには、機能的に手動の繰り返しに相当する代替手法がいくつか用意されています。jQuery を使用して繰り返しを行うと、コードがコンパクトになり、読みやすさも向上します。まず、each 関数を使用する方法があります。
前に述べたように、jQuery の each 関数は、ラップされたセットに関連付けられた任意の要素に対してユーザー定義コールバックを実行します。ただし、ラップされたセットに対する一般的な操作の実行をすばやく簡単にする方法が多数存在します。 たとえば、css 関数を使用すれば、ラップされたセットに CSS スタイルを適用できます。フォーム内のすべての入力要素の背景色と境界線スタイルを設定する例を次に示します。
$("form input").css( {'background-color' : 'yellow', 'border-style' : 'dashed'} );
正直なところ、この短い例はやや誤解を招く可能性があります。なぜなら、CSS 自体で問題なく実行できるようなことにも jQuery の使用を推奨しているように捉えられるからです。css 関数は、ユーザーとの対話などの実行時条件に基づいて動的に適用されるスタイルを扱う場合に便利です。
同様に、ラップされたセット内の要素に対して、CSS クラスを追加、削除、または切り替えることができます。これは、addClass、removeClass、および toggleClass 関数を使用して実行できます。attr 関数を使用すると、すべての要素に対して 1 つまたは複数の属性を設定できます。たとえば、すべての入力要素を無効にする例を次に示します。
$("form input").attr( {'disabled' : 'disabled'} );
html 関数は、タグの HTML コンテンツを設定します。この関数は、内部で innerHTML プロパティを使用します。タグの内部テキストを設定するには、text 関数を使用し、設定するテキストを引数として渡します。これは、jQuery のように複数のブラウザに対応するライブラリの利点を理解するための良い方法です。innerHTML プロパティは、すべてのブラウザで同じようにサポートされている事実上の標準プロパティと考えることができます。
このことは、それと類似した、テキストを設定するだけのプロパティには当てはまりません。このプロパティは、Internet Explorer では innerText、Firefox では textElement という名前です。jQuery の text 関数は、それらの違いを隠し、すべてのブラウザで同じ機能を提供します。
jQuery のチェーン機能
jQuery の最も優れた機能の 1 つが、チェーン機能です。これは、jQuery オブジェクトそれ自体、および関数とフィルタのほとんどが jQuery オブジェクトを返すことから可能になる機能です。返されるオブジェクトには、元のラップされたセットがその関数によって変更された結果が含まれています。たとえば、ラップされたセットに css 関数を適用した場合、返される jQuery オブジェクトには、同じ要素のセットが、変更された CSS スタイルのセットと共に含まれます。フィルタを適用すると、関数によってフィルタ処理された結果として、より小さなセットが返されます。指定されたクエリに一致する要素をすべて除外する not 関数が用意されていることも覚えておいてください。
jQuery 関数を連結するのはごく簡単です。前の呼び出しで返された jQuery オブジェクトに、新しい関数呼び出しを関連付けるだけで済みます。その例を次に示します。
$("form input") .not("[type!=text]") .css( {'background-color' : 'yellow', 'border-style' : 'dashed'}) .attr("value", "test");
この例の式では、type 属性が text に等しいすべての入力フィールドが選択され、いくつかの CSS スタイルと value 属性を固定値に設定しています。この例では、not 関数を単にチェーンに 3 番目のリンクを追加するためにだけ使用していることに注意してください。not 条件の結果を $ クエリに統合することもでき、その方がコードは見やすくなります。
チェーン機能を用いるとコードがコンパクトになるのは言うまでもありませんが、コードの実行は必ずしも速くなりません。チェーン機能は、手法として開発者の要望にかなう場合とそうでない場合があります。式をコンパクトにしたことで問題が生じる場合は、デバッグを単純化するために式をあらためて分割する必要があります。
最後に、すべての jQuery メソッドが変更された jQuery オブジェクトを返すわけではないことに注意してください。たとえば、html や text のようなメソッドは、ソースであるラップされたセットから、最初の要素の HTML またはテキスト コンテンツをそれぞれ示す文字列を返すだけです。jQuery メソッドの厳密な構文については、docs.jquery.com/Main_Page を参照してください。
HTML を理解する
jQuery について深く知るにつれて、作業中の HTML を詳しく理解することの重要性がわかってきます。ASP.NET サーバー コントロールは、出力する HTML の構造を隠す傾向にあります。その一方で、サーバー コントロールは、開発者が HTML の詳細よりも宣言型属性に専念できるよう導入されたものです。長年の経験を経て、それが必ずしも常に正しいアプローチでなかったことが明らかになりました。
今日では、アクセシビリティ、スタイル設定、および XHTML への準拠のために、HTML を完全な制御下におくことが必要になっています。偶然にも、このことによって、jQuery と ASP.NET MVC フレームワークとの間にちょっとしたリンクが確立されました。そして、ASP.NET MVC フレームワークのパッケージに jQuery の最新バージョンが含まれていることは、まったく偶然ではありません。
とは言え、jQuery セレクタを使用してロジックをマークアップに結び付けると、ロジックと DOM の形状との間に無用な関連性が生じ、結果としてアプリケーションの保守性が低下する場合もあるので、注意が必要です。
最後に、JavaScript を興味深い方法で使用する他のアイデアをお探しの場合は、MSDN の JavaScript に関する記事の一覧をご覧ください。
ご意見やご感想は、cutting@microsoft.com まででお送りください。
Dino Esposito は、IDesign 社のアーキテクトであり、『Microsoft .NET:Architecting Applications for the Enterprise』(Microsoft Press、2008 年) の共著者です。Dino はイタリアに在住し、世界各国で開催される業界のイベントで頻繁に講演しています。ブログは weblogs.asp.net/despos で読むことができます。