こんにちは、太田です。今回はGoogle Chrome拡張に使えるHTML5関連技術の2回目をお送りします。
前回はcanvas、ドラッグ・アンド・ドロップを取り上げましたが、今回はHTML5周辺の技術として、ECMAScript 5やCSS3の先行実装を取り上げます。ECMAScript 5は昨年末(2009年12月)にリリースされたばかりですが、WebKit・Chromiumでは早速(実際にはかなり先行して)その実装が進められています。またCSS3についても、多くのモジュールがWorking Draft(草案)の段階ですが、WebKitでは先行実装がされており、Chrome拡張ではその機能を存分に試すことができます。前回も書きましたが、Chrome拡張はそういった最新技術を試すのに格好のプラットフォームです。
Chrome拡張で使えるECMAScript 5
Google ChromeのJavaScriptエンジンはGoogle製のV8ですが、V8はWebKit(Safari)のJavaScriptCoreとの互換性を意識して実装が進められています。そのため、多くのECMAScript APIはJavaScriptCoreで実装されたらV8にも実装されるという流れを踏んでいます。JavaScriptCoreでのECMAScript 5の実装状況はQt Labs Blogs ≫ ECMAScript 5 and WebKit/JavaScriptCoreで、V8についてはECMAScript 5 and Chromium/V8 - 0xFFでまとめられています。
Native JSON
まず、なんといってもECMAScript 5ではJSONが正式にサポートされた点が大きなニュースです。JSONをサポートするプログラミング言語が増えてきた昨今、ECMAScript発であるJSONを今ごろになってECMAScriptが正式にサポートというのは少々驚かれるかもしれません(それだけECMAScriptの改訂が止まっていた、と言えます)。
JavaScriptにおけるJSONのメソッドは、JSON.stringifyとJSON.parseの2つだけです。
JSON.stringifyは第一引数に渡したオブジェクトをJSON文字列に変換するメソッドです。第3引数に数値を渡すとその数値だけインデントさせることができます。第3引数には文字列を持たすこともできるので、\tを渡せばタブインデントさせることも可能です。
JSON.stringifyの第2引数には関数を渡すことで(主にイレギュラーなデータの扱いについて)出力をカスタマイズすることができます。上記のreplacerの例のように、日付をミリ秒で出力したり、通常は無視されてしまう関数を文字列として出力するといったことが可能です(なお、余談ですがFirefox3.5ではstringifyの第2引数についてバグがあるため、意図通りの結果を得られません cf:Bug 512447)。
また、オブジェクトのtoJSONメソッドを書き換えることで、特定のオブジェクトについて出力をコントロールすることも可能です(ただし、この機能のためprototype.jsを読み込んだ環境でJSON.stringfyを使用すると意図しない結果になってしまう現象が起こるので注意が必要です)。
JSON.parseはJSON文字列をJavaScriptのオブジェクトに変換します。第2引数はやはり出力をカスタマイズすることができるので、上記replacerの逆の処理を行うことで柔軟にオブジェクトをやり取りすることができるようになります。
なお、このJSONですが、JavaScriptの感覚で書こうとすると必ずと言っていいほど正しくないJSONを書いてしまいます。JavaScriptでのオブジェクトの表記法は曖昧さを許容するゆるい仕様ですが、データ記述言語としてのJSONは曖昧さを許さないためです。特に間違いやすいのは、文字列を囲むときにダブルクォートを使用しなければいけない(シングルクォートは使えない)点、キーもダブルクォートで文字列として表記しないといけない点の2つです。JSONは手で書くのではなく、ライブラリやJSON.stringifyで出力させるのがよいでしょう。
Array拡張
配列メソッドとしてindexOf, lastIndexOf, every, some, forEach, map, filter, reduce, reduceRightが追加されています。indexOf, lastIndexOfは配列を検索し、最初に一致した添字を返すメソッドです。それ以外のメソッドはforEachに代表されるように、配列の各要素を順番に処理するメソッドで、それぞれ結果の扱い方が少しずつ異なります。
このArray拡張はFirefoxでは1.5からサポートされていますし、Google Chromeもリリース当初からサポートしているメソッドで、prototype.jsなどのライブラリで同種のメソッドが古くから実装されてるので、すでに定番となっていると言えます。
Object.keys
Object.keysはオブジェクトのキーを配列で取得するメソッドです。先述のArray拡張と組み合わせて、オブジェクトを柔軟に処理できるようになる便利なメソッドです。
そのオブジェクト自身が持つプロパティのみを列挙し、prototypeは辿りません。
Object.keysを従来のJavaScriptで実装すると、下記のようになります。
なお、Object.keysでは、第1引数にObjectでないものを渡すとTypeErrorになると定義されているので、instanceof Objectでチェックするようにしました。typeofが"object"であるかという点でチェックする方法もありますが、前者ではnullでTypeErrorに、後者ではTypeErrorにならないという違いがあります。
Object.create
※2010年1月にリリースされたGoogle Chrome 4.0.249.78(安定版)はObject.createが実装される前のバージョンとなったため、上記バージョンではObject.createは使用できません。ご了承ください。
Object.createはオブジェクトを定義するためのメソッドです。prototype継承を簡略化し、従来のJavaScriptではできなかった、列挙できないプロパティや変更不可能なプロパティを作ることができます。
Object.createは第1引数でprototypeとなるオブジェクトを渡し、第2引数は省略可能で、そのオブジェクト自身のプロパティを定義します。valueは値、writableは変更可能かどうか、enumerableはfor inなどで列挙されるかどうか、configurableはdelete演算子でプロパティを消せるかどうかとwritable, enumerable, configurableを変更することができるかどうかを決めます(ただし、現在のChrome(V8 2.0.5.5)ではconfigurableプロパティは実質サポートされていません)。
Object.createの第2引数で定義するプロパティは、writable、enumerableを省略するとデフォルトでfalseにセットされるため、上記のように冗長な記述が必要になってしまいます。第2引数は書き換えを禁止したい、列挙させたくないプロパティを定義する際に使用するとよいでしょう。
CSS3
Google Chromeは最新のWebKitを採用していますので、CSS3の先行実装を試すことができます。そのなかでも、Chrome拡張ですぐに使えるテクニックをいくつか紹介します。
border-radius
border-radiusはいわゆる角丸を実現します。WebKitでは-webkit-border-radiusのようにプリフィックスが付きます。将来的にはこのプリフィックスは不要になる点に注意が必要です。実際、Chrome 4はプリフィックスなしの記述に対応していますので、Chrome拡張ではプリフィックスなしの記述を使用しても問題ありません。
gradient
gradientは背景などでグラデーションを実現します。
CSSの応用
下記のようなCSSでボタンにスタイルを当てると、画像を使わずにスタイリッシュなインターフェースを作成できます
まとめ
今回はChrome拡張で使えるHTML5周辺技術としてECMAScript 5とCSS3を取り上げました。次回はさらにHTML5周辺技術から、CSS transformsや、Web StorageやWeb SQL databaseなどのAPIを取り上げる予定です。