IE用HTML5新要素のMinify生成
Updated / Published
latest logさんでエントリーされていたコードを削る方法がすごく勉強になったので、練習がてらに早速IE8以下でHTML5の新要素をCSSセレクタで使う際にdocument.createElement()で事前に書き出しておく必要があるコードをMinify化してみました。
書き出す必要のあるHTML5の新要素
まず最初に、IE8以下では未知の要素となるために書き出す必要のあるHTML5の新要素名を列挙しておきます。
article
要素aside
要素nav
要素section
要素hgroup
要素header
要素footer
要素figure
要素figcaption
要素time
要素mark
要素
この他にも、HTML5の新要素にはcanvas
要素, audio
要素, embed
要素, video
要素, source
要素, progress
要素, meter
要素, ruby
要素, rt
要素, rp
要素, details
要素, summary
要素, datalist
要素, keygen
要素, output
要素, command
要素, menu
要素(※menu
要素はHTML2から規定されている要素名ですが全く異なる用途として新たに導入されています)があるのですが、この内、embed
要素はIE3から、ruby
要素,rt
要素,rp
要素はIE5のバージョンから既に先行実装済みであり、その他の要素についてはCSSで整形できるものでなっかり、全く機能すらしないのでdocument.createElement()
で書き出す必要はありません。
Minify化のポイント
latest logさんからポイントを抜粋させてもらいます。
ドット演算子以降を自力で Minify する
JavaScriptは動的な言語なので、ドット演算子以降は基本的に minify しても圧縮されません。
document.createElement("div"); document.createElement("a"); document.createElement("p");
↓ このままだと、minify しても縮まらない
document.createElement("div");document.createElement("a");document.createElement("p")
ドット演算子によるアクセス( Object.property )は、Object["property"] のシンタックスシュガー(糖衣構文)です。
これらは、同じ処理速度でほぼ同じ価値を持ち、見た目がちょっと違うだけ(ドット演算子は制限も多いけど)。
そこで minifier が処理しやすいように、シンタックスシュガーを解除すると
var doc = document, createElement = "createElement"; doc[createElement]("div"); doc[createElement]("a"); doc[createElement]("p");
↓ minify
var a=document,b="createElement";a[b]("div");a[b]("a");a[b]("p")
すごいですよね、可読性は犠牲になりますが、同じ処理速度で且つここまで削ることができるというのは、目から鱗でした。
早速この書き方を取り入れて、HTML5の新要素を書き出してみます。
HTML5の新要素をIE8以下で認識させるためのコード例
代表的なライブラリにhtml5.jsがありますが、これと同様のことができる最小コードへの試みです。
var a=document,b="createElement",c="article,aside,nav,section,hgroup,header,footer,figure,figcaption,time,mark".split(','),i=c.length;while(--i>=0)a[b](c[i]);
よしなかなかシンプルにできたぞと思っていましたら、ppBlog officialさんでもまったく同じようにHTML5新要素のdocument.createElement()
の最小書き出しがエントリーされていました。書き出している要素は便宜上異なっていますが、ppBlogさんで紹介されているコードの方がいろいろなアプローチで断然ショートでした。
どこで最初に見かけたのか失念しましたが、これを一行(ワンライナー)で簡潔に済ませたスクリプトを見たときはいたく感心しました。Dean Edwards氏のブログ もこうなっています。
"header,nav,article,section,aside,footer".replace(/\w+/g, function(a){document.createElement(a)});
上のポイントは、replaceメソッドの引数に関数を指定できて、その関数内では、正規表現にマッチした要素を適宜適用していく点です。ループみたいなことを勝手にやってくれる点ですね。おそらくこれ以上短くは書けないのではないかと思うのですが、息抜きに自分なりにいくつか考えてみました。
"header,nav,article,section,aside,footer".split(',').sort(function(a){return document.createElement(a)*1});
これも、似たような発想からですね。自動でなんかやってくれるという。
with("header,nav,article,section,aside,footer".split(',')))while(length)document.createElement(pop());
ここではwith構文を使ってみました。これもなかなかシンプルです。同じくwithと、Enumeratorを使って、
with(new Enumerator("header,nav,article,section,aside,footer".split(',')))for(;!atEnd();moveNext())document.createElement(item());
これは、ちょっと長いし、Enumerator Object はマイナーですかね。
短さ命で、グローバル変数の汚染なんて気にしないぜっ、という向きには以下のようなものもありかと思います。
s="header,nav,article,section,aside,footer".split(',');while(s[0])document.createElement(s.pop());
for文関連では、
for(i in s="header,nav,article,section,aside,footer".split(','))document.createElement(s[i]);
とか
for(i=0;n="header,nav,article,section,aside,footer".split(',')[i++];document.createElement(n));
とかですかねぇ。
コードを短くためのアプローチは本当勉強になります。なお、これらの書き方をしたからといってパフォーマンスがどの程度最適化されるのか等についてはわからないので、飽くまでもコード自体をMinify化するためのアプローチとして受け取ってください。