mofmof.js で日本語コメントの併記を始めました
uupaa.js の開発中に、
- 図形を交えたり、コードの由来を説明する外部リンクをソースコードに埋め込む オンラインコメントスタイル おすすめ
- 独自○○ より オレオレ○○ と呼べばいいよ。オレオレライブラリとか、オレオレスタイルとか
- オレオレコーディングスタイルを発明せず、JS特有の事情を考慮しつつ、既存のコーディングスタイルを流用するといいよ
- == ではなく === おすすめ
- typeof hoge == "undefind" より hoge === void 0 おすすめ
- ナビ子記法 おすすめ
など、2008年頃は存在しても注目されてなかったり、存在もしなかった用語や用法をこさえたりと、色々やったりしてました。
uupaa.js のベースライブラリとなる、現在開発中の mofmof.js でも
- 日本語コメントを併記 してみたり
- 短さよりも、最適化と可読性のバランスを考慮したコードや、対称性を重視したコードに してみたり
- 経験を踏まえて、prototype拡張として実装するのが自然なものは、prototypeの下に置くべき とか考えなおしてみたり
- Titanium, NGCore, Windows 8 で最適化されるように ビルドオプション追加してみたり
などをやり始めています。
日本語コメントはこんな感じ
http://code.google.com/p/mofmof-js/source/browse/trunk/0.1/src/mofmof.js
はてなダイアリーだと、横幅が厳しい感じですね。
// mm.factory - Class and Nodes instance factory function mm_factory(expr, // @param ClassNameString/NodeQueryExpressionString/ // 引数: クラス名, Node検索文字列, Nodesインスタンス, Node, Nodeの配列 // NodesInstance/Node/NodeArray: arg1, // @param Mix/Node/NodesInstance(= undefined): // 引数: クラスインスタンス生成時の第一引数 または Nodes に渡すコンテキスト(省略可能) // class arg1 or Nodes Context arg2, // @param Mix(= undefined): class arg2 // 引数: クラスインスタンス生成時の第二引数(省略可能) arg3, // @param Mix(= undefined): class arg3 // 引数: クラスインスタンス生成時の第三引数(省略可能) arg4) { // @param Mix(= undefined): class arg4 // 引数: クラスインスタンス生成時の第四引数(省略可能) // @return ClassInstance/NodesInstance: // 戻り値: クラスインスタンス または Nodes インスタンス if (typeof expr === "string" && Class[expr]) { // 文字列が指定され、それが mm.Class に登録済みならクラスインスタンスを生成する return new Class[expr](arg1, arg2, arg3, arg4); // クラスインスタンスを生成し返す。適用される引数は最大で4つ } return new Nodes(expr, arg1); // Nodesインスタンスを生成し返す。適用される引数は最大で1つ }
Prototype拡張はこんな感じに
http://code.google.com/p/mofmof-js/source/browse/trunk/0.1/src/object.js
上記のソースコードでは、Object, String, Number, Date, Array, Boolean, Function などに
- ECMAScript-262 5th 由来のもの
- Ruby 由来のもの
- JSON 由来のもの
を入れ込んでいます。
Prototype.js のように既存のネイティブコードを上書きするような事もありません。
// --- Object --- // Object.keys() // --- Array --- // Array.isArray() Array.toArray() Array.range() // Array#range() Array#f() Array#or() // Array#and() Array#fill() Array#clean() // Array#clear() Array#clone() Array#unique() // Array#toHash() Array#indexOf() Array#lastIndexOf() // Array#map() Array#some() Array#every() // Array#filter() Array#forEach() Array#flatten() // Array#reduce() Array#reduceRight() // --- Date --- // Date.now() Date#toJSON() // --- Boolean --- // Boolean#toJSON() // --- Number --- // Number.unique() Number#has() Number#pad() // Number#clip() Number#toJSON() Number#inRange() // Number#toHexString() // --- Function --- // Function#bind() Function#build() // --- String --- // String#f() String#has() String#trim() // String#trimTag() String#trimQuote() String#repeat() // String#toHash() String#toJSON() String#sprintf() // String#truncate() String#toByteArray() // --- JSON --- // JSON.parse() JSON.stringify()
正規表現を明記せず、RegExp#exec を String#split にするとちょっとハッピーに
JavaScript の小ネタです。
UserAgent 文字列(window.navigator.userAgent)
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.814.0 Safari/535.1"
から、Windowsのバージョン(6.1)を取り出すようなコードをよく見かけますね。
ちょっと前の私は RegExp#exec + parseFloat で、こんな(↓)感じにしていたり、
function getWindowsVersion() { var m = /Windows NT (\d+(\.\d+)?)/.exec(navigator.userAgent); if (m) { return parseFloat(m[1]); } return 0; }
こんな(↓)感じにワンライナーにしちゃってましたが、
var version = parseFloat((/Windows NT (\d+(\.\d+)?)/.exec(navigator.userAgent) || [,0])[1]);
最近は、String#split + parseFloat で、もっとシンプルにしてるよ!
var version = parseFloat(navigator.userAgent.split("Windows NT")[1]) || 0;
正規表現やめちゃって文字列に。
切り出した文字列に含まれる空白は parseFloat(" 6.1") → 6.1 って感じにトリミングされるので、parseFloat にお任せしてます。
正規表現を明記しないことで、こんなにいいことが! 的なオマケ
IE10 からは、UserAgent に埋まっている Version 番号が二桁になりますね。
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
ブラウザのバージョン番号が二桁になるシーズンになると、各ブラウザベンダーのブログ(過去においてはIE や Opera のブログ)(おそらくは来年の Firefox のブログ)には、
「バージョン番号の取得に /MSIE (\d\.\d)/ のような一桁の数字しか取得できないコードが埋まってると、間違ったバージョンが取得されちゃうかもしれない…」なエントリが乗ったりするのですが、
String#split() + parseFloat で取得するようにすれば、いいんじゃないかな!? って思います!
Opera の userAgent に謎の Version番号(9.80) が埋まってるのも、これ(↑)が理由なんだよね
"Opera/9.80 (Windows NT 6.1; U; ja) Presto/2.9.168 Version/11.50"
HTML5の文字エンコーディングの判定は 512byte または 1024byte 以内までに
HTML5のWorking Draft(20110113)までは、文字エンコーディング判定の範囲はファイルの先頭512byte以内と定義されていました。
そのため、
<!DOCTYPE html> <!--[if IE 8 ]><html lang="ja" xmlns:og="http://ogp.me/ns#" xmlns:mixi="http://mixi-platform.com/ns#" xmlns:fb="http://www.facebook.com/2008/fbml" class="ie8"><![endif]--> <!--[if IE 9 ]><html lang="ja" xmlns:og="http://ogp.me/ns#" xmlns:mixi="http://mixi-platform.com/ns#" xmlns:fb="http://www.facebook.com/2008/fbml" class="ie9"><![endif]--> <!--[if (gt IE 9)|!(IE)]><!--><html lang="ja" xmlns:og="http://ogp.me/ns#" xmlns:mixi="http://mixi-platform.com/ns#" xmlns:fb="http://www.facebook.com/2008/fbml"><!--<![endif]--> <head>
といった、546byteの文字列の後に
<meta charset="UTF-8"> <title>こんにちは!こんにちは!</title>
とやってしまうと、正しく判定されるのか? ちょっと危うい気がしてしまいます。
http://www.w3.org/TR/2011/WD-html5-diff-20110405/ に書かれているように、
現在では、「512byte」→「1024byte」に改訂されています。
この時期に登場した IE9 はどちらの仕様でビルドされているのでしょうか? ちょっと気になりますね。
また、IE10pp2 からは ↓ のようなコンディショナルコメントは利用できなくなります(スルーされます)。
<!--[if IE 8 ]> <![endif]-->
ここ大事ですので、忘れないようにしましょう。
2011-07-10追記
IE9.01 は 512byte なんだろうか、それとも昔のIEのように、もっと先まで読んで判別しているのだろうか? という所が知りたくて、EUC-JP なファイル等も作ってみたのですが、文字化けしている状態でユーザが正しいエンコードを指定しなおすと、それ以降エンコードのパターンを学習する(またはエンコードに利用するバリエーションが増える)ような動きがあるらしく(その動きもあって、こちらの予想とは違う結果が出てしまう)、なんだかモヤモヤしたままです。
添付画像は、IE9.01 で http://jp.msn.com を開き、エンコードを[日本語 (自動選択)] にしたら文字化けしたよ の図
パーティクル3万個
IE 10pp2 と iPad2 (iOS5) のスコアを追記しました
iPhone4S (iOS5) のスコアを追記しました
Firefox 4 から window.mozRequestAnimationFrame が利用可能になっています。
window.requestAnimationFrame / setTimeout(,4) / setInterval(, 16) で パーティクル3万個を飛ばすデモ。
ベンチマークマシンのスペック → MacBook (13-inch, Late 2009) - 技術仕様。
メモリ4GBに + BootCamp + Windows7 上で計測しています。
Windows エクスペリエンスインデックスの数値は、5.1 で、各項目は
- プロセッサ: 5.8
- メモリ: 5.8
- グラフィックス: 5.1
- ゲーム用グラフィックス: 5.5
- プライマリハードディスク: 5.9
となっています。
各ブラウザのスコアはこちら
requestAnimationFrame または setInterval(16)
Browser | fps | method |
---|---|---|
IE 9.0.1 (x86) | 45 | setInterval(, 16) |
IE 9.0.1 (x64) | 17 | setInterval(, 16) |
IE 10 pp1 | 45 | setInterval(, 16) |
IE 10 pp2 | 44 | msRequestAnimationFrame |
IE 10 pp2 | 44 | setInterval(, 16) |
Safari 5.1 beta | 50 | setInterval(, 16) |
Firefox 5 | 60 | mozRequestAnimationFrame |
Chrome 14 | 60 | webkitRequestAnimationFrame |
Opera 11.11 | 62.5 | setInterval(, 16) |
iPhone 3GS (iOS4.3.3) | 5.2 | setInterval(, 16) |
iPhone 4GS (iOS5) | 14.1 | setInterval(, 16) |
iPad 2 (iOS4.3.3) | 12.9 | setInterval(, 16) |
iPad 2 (iOS5.0) | 17.6 | setInterval(, 16) |
Firefox 5 (DHD) | 20.5 | mozRequestAnimationFrame |
MobileWebKit 533.1 (DHD) | 3.9 | setInterval(, 16) |
MobileWebKit 533.1 (GP) | 5.2 | setInterval(, 16) |
setTimeout(4) で実行
Browser | fps | requestAnimationFrame または setInterval(16)と比較して | |
---|---|---|---|
IE 9.0.1 (x86) | 41 | やや遅くなる | |
IE 9.0.1 (x64) | 16.5 | やや遅くなる | |
IE 10 pp1 | 42.5 | やや遅くなる | |
Safari 5.1 beta | 43 | やや遅くなる | |
Firefox 5 | 100 | とても速くなる(速くなりすぎる?) | |
Chrome 14 | 60 | 変化なし | |
Opera 11.11 | 95 | とても速くなる(速くなりすぎる?) | |
iPhone 3GS (iOS4.3.3) | 5.1 | 変化なし | |
iPhone 4GS (iOS5.0) | 13.5 | やや遅くなる | |
iPad 2 (iOS4.3.3) | 12.9 | 変化なし | |
iPad 2 (iOS5.0) | 16.4 | やや遅くなる | |
Firefox 5 - (DHD) | 20.2 | やや遅くなる | |
MobileWebKit 533.1 - (DHD) | 5.2 | やや速くなる | |
MobileWebKit 533.1 - (GP) | 5.2 | 変化なし |
※DHD = HTC Desire HD (Android OS 2.2)
※GP = GALAPAGOS SoftBank 005SH (Android OS 2.2.1)
このテストでわかったことは、
・MobileWebKit 533.1 で動かすとパーティクルが緑色で表示される(バグかな?)
・setTimeout(4)はsetInterval(16)に比べ負荷が高くなる傾向がある
・Firefox 5 と Opera 11 は setTimeout(4) に追従している。未来を感じる
・iOS 5.0 の MobileSafari は window.webkitRequestAnimationFrame() 未実装
Number.prototype.toHexString
数値(num)から4桁のゼロ埋めされた16進文字列が欲しい場合に
var num = 123; var rv = ("000" + num.toString(16)).slice(-4); alert( rv ); // "007b"
と毎回書くのもアレなので、こんな感じに書けるといいんじゃないでしょうか。
alert( (123).toHexString(4) ); // "007b"
実装してみました。
//{@prototype (function(_DEC2HEX) { // create HEX2 cache for (var i = 0x100; i < 0x200; ++i) { _DEC2HEX[i - 0x100] = i.toString(16).slice(-2); } Number.prototype.toHexString = function(n) { // @param Number(= 2): digits. 1 ~ 8 // @return String: HexDigitString // [1][omit arg] console.log( (1).toHexString() ) -> "01" // [2][n = 1] console.log( (1).toHexString(1) ) -> "1" // [3][n = 2] console.log( (255).toHexString(2) ) -> "ff" // [4][n = 8] console.log( (255).toHexString(8) ) -> "000000ff" // [5][Math.floor] console.log( (1.1).toHexString(2) ) -> "01" // [6][Math.abs] console.log( (-1).toHexString(2) ) -> "01" var val = (this < 0 ? -this : this) | 0, digit = (n === void 0 || n <= 0) ? 2 : n; if (digit === 2) { return _DEC2HEX[val & 0xff]; // use cached string } return ("0000000" + val.toString(16)).slice(-digit); }; })(Number.prototype._DEC2HEX = {}); //}@prototype
小数点以下を切り捨て、負の数値は正の数値として処理した16進数文字列を返します。
先頭に"0x"は付きません。toHexString(n) の n で指定された長さまでゼロフィルを行います。
結果の文字列の長さが n より長い場合は、下 n 桁の文字列を返します(上位の桁を切り落とします)。n は省略可能です。省略した場合は n = 2 を指定した場合と同じ結果になります。n に 1以下の値や無効な値を指定すると n = 2 と同じ結果になります。
n = 2 の場合に限り、予め作り貯めておいた Hash ( Number.prototype._DEC2HEX ) から文字列を検索し、わりと素早く結果を返す気がします。
あと、Number.prototype._DEC2HEX は他の処理からも使いまわす予定なので、Number.prototype にくっつけてます。
日本語の説明を読むよりも、コードを読んだほうが簡単ですね!
Number.prototype.toHexString - jsdo.it - share JavaScript, HTML5 and CSS
IE9 日本語版 非公式ダウンロード
追記: 2011-04-26 00:00 より日本語版が正式にリリースされるとのこと
Internet Explorer(R) 9 日本語版の提供日について
2011 年 4 月 6 日日本マイクロソフトは、このたびの震災に伴い、重要な通信インフラとなっているネットワーク回線への負荷軽減への配慮などから、 3 月 15 日(火)午後 1 時(日本時間)に予定されていた最新ブラウザーInternet Explorer(R) 9 日本語版の製品版提供の延期をしておりましたが、このたび新たな提供日を 4 月 26 日(火)午前 0 時(日本時間)と決定しましたのでご案内申し上げます。なお、ネットワーク回線への負荷軽減のため、同日はダウンロード提供のみで、当初同日実施を予定していたベータ版・製品候補版ユーザー向けの自動更新については後日段階的に実施する予定です。
via http://www.microsoft.com/japan/presspass/news/default.aspx#110406
震災の影響で、IE9 日本語版の正式リリースは残念ながら延期されていますが、ファイルは既に存在するとのこと。
IE9 を入れると IE8 環境が無くなってしまいますが、IE8 互換モードで十分にカバーできるため、インストールできる人は躊躇せず入れてしまうべきです。
# 私は Windows7 32bit, 64bit, Windows Vista 32bit の計3台の環境を IE8 から IE9 にしました
# Vista Ready PC(3〜4年ものの非力なPC)でも、IE9 はちゃんとキビキビと動いてくれていました
IE9 が出たから、二つ前のバージョンの IE7 と IE6 にはお引き取り願わないとね!
IE9 はリリース後のわずか一日でブラウザシェアの0.8%をモギリ取ったようです(in 北米)
http://gs.statcounter.com/#browser_version-na-daily-20110315-20110316-bar
Google Chrome、1日で1%のシェア獲得 - ITmedia NEWS といい勝負なんではないでしょうか。
DOM Lv0 イベントハンドラ内で media 変数にアクセスできない
IE6〜IE9RC では、 DOM Lv0 イベントハンドラ内では media 変数にアクセスできないようです。謎です。
var media = "(ε・◇・)з はろー"; <!-- IE6〜IE9RCで動作しないケース --> <input type="button" value="IEだとmedia変数が見えないよ" onclick="alert(media)" /> <!-- window.media と明示すれば大丈夫そそうだけど… --> <input type="button" value="window.media変数は見えるよ" onclick="alert(window.media)" />