ykzts.com

JavaScriptは決して遅くない

著者: 山岸和利
更新: 編集履歴

数年前ならいざ知らず、現代のJavaScriptは充分に高速な動作が実現されている。無論C言語で記載されたいわゆるネイティブアプリケーションと比較すれば計算速度等では大きく劣ってしまう。だがしかし複雑な計算等を必要としない通常範囲のアプリケーションであればJavaScript (とHTMLとCSS) で記述がなされたアプリケーションの実行速度はネイティブアプリケーションと遜色ないものになると半ば強い確信を抱いている。ではJavaScriptで記述がなされているアプリケーションの動作が緩慢であるという認識がなぜ多くの場でなされているのか。それは単純な理由である、そのアプリケーションの作者が知識不足でDOM操作が冗長的なものとなっており無駄が多くなってしまっているからだ。

JavaScriptの動作が速くなろうとも、DOM操作は現在でも多くの場面で遅くなってしまっている。document.getElementsByTagNamedocument.getElementsByClassName などで取得することとなる HTMLCollection オブジェクトや NodeList オブジェクトはその仕様上、取得後であってもHTML文書が変更されるごとにその内容の更新が行われており、内部的に常に処理を実行させ続ける必要がある。そのために濫用激しければ致命的なまでの速度低下を招いてしまう。これはHTML文書に含まれる要素が増えれば増えるほどに顕著なものとなってしまう。Array.prototype.slice.call(document.getElementsByTagName('a')) のようなかたちにして HTMLCollection オブジェクトや NodeList オブジェクトから Array オブジェクトへと形を変容させることによってある程度の改善を計れる。このほかにもDOM関連の処理は簡単に動作を遅くさせてしまうものばかりであり、安易な使用は自身の首を締めるだけの結果となってしまう。

先の段落で記載した HTMLCollection オブジェクトや NodeList オブジェクトを Array オブジェクトへと変換させるのと同種のことはjQueryの内部でも行われてあり、その結果として雑に書かれたスクリプトであればjQueryを使用しているものの方が高速に動作することとなってしまっている。jQueryは読み込み時に互換性確保のために通常は不要となる処理を多く実行させており、非常に動作が遅い。jQueryが速いのではなく、自身の書き方に問題があるのだと、初めに正しく自認することが肝要となっている。

ではどのような記述が速度向上には有効であるのか。これは難しい問題である。かくいう私自身も方法を未だに正しく確立できていない。一先はDOM操作を省略させていくのが安定した方法ではなかろうかと考える。JavaScriptを用いて任意の要素に対し style 属性の値を一つ一つのプロパティーを与えるような処理は避け、スタイルシートに任意のクラスを設定した上でプロパティーを事前に記載しておき、JavaScriptを用いて行うのは任意の要素に対する class 属性の値を変更するのみに留めておくのが速度の面で考えれば優秀なのではないだろうか。またアニメーションを行わせる場合についても同様である。動きが起こるつどに動的に任意の要素に対して位置情報に関する値を一つ一つ追加していくのは、速度の著しい低下を招き、アニメーションが汚らしく見えてしまう恐れもあるだろう。こちらも先の対処と同様に class 属性値のみを変化させ、アニメーション自体はスタイルシートに transition プロパティーや animation プロパティーを用いた記載を行う。これによりある程度のアニメーションであれば問題なく扱えるのではないかと推測する。もちろんそれだけでは対処できない事案もあるだろう。適材適所に思案し、適切なコードの記述を行う必要があるのだろう。

また任意のノードを取得するには無論相応の処理時間がかかってしまう。複数回の処理が行われることが明白であるのであれば、任意のノード取得後に適切な変数へ格納することが当然のことではあるが重要となるだろう。この点は基礎的なことであろうとは思うのだが抑えられていないコードは現在にも未だ多く目にする。特にjQueryに依存したコードでは顕著である。jQueryの内部的に簡易的なキャッシュがなされているとはいえ、あまりにも迂闊であると言わざるをえない。

加えてインターネット上に限られた情報しかなく、使用方法をつかむのに多少の手間はいるだろうが、DOM RangeDocumentFragmentインターフェースを使うのも有効であろう。特にDOM Rangeは操作するHTML文書のノードが多ければ多いほどに顕著なまでの速度向上が見込める。先の記載の通りにインターネット上には限られた情報しかないが、W3Cの仕様に書かれている以上の動作はしない。なのでウェブブラウザーでの動作を確認しつつ、幾通りかの記述を実際に行ってみれば、既にある程度のDOM操作を行えるようになっている人物であれば習得は難しくないのではないだろうか。必ずしも要るという場面は極めて稀であろうが、知識として有しておいて損はないだろう。

繰り返しになるが現在のJavaScriptは遅くない。古くは並列処理ができなかった。だが現在はWeb Workersを用いることにより並列処理を行えるようになっている。Web Workersはこの記事を執筆している時点ではまだ勧告候補の段階ではあるが、現時点でも多くのウェブブラウザーで安定して動作するようになっている。使うにあたって心配する点はない。正しく気を遣いさえすればネイティブアプリケーションに遜色ないアプリケーションをJavaScriptを用いて作れる。なにを心配する必要があろうか。

関連記事

はてなブックマークの人気エントリーをながめていたところJavaScriptでアニメーションを書く初歩の初歩のような記事が目にはいりました。初歩であればこそ、この記事で省かれているrequestAnimationFrameの話をするべきではないのかとも思いますが、それよりもわたしは元の記事に掲載されているコードがJavaScriptを用いて十ミリ秒の間隔を開けて複数の処理を何度もウェブブラウザーにさせてしまっていることが気になりました。また、いくつかの処理を完了させてから、setTimeoutを用いて任意の時間が経過するのを待ち、同様の処理を行うというかたちになっていますので、処理に時間がかかってしまえば、なめらかな描写は到底実現されないものとなってしまっています。

HTML.jsというJavaScriptで楽にDOM操作を行えるようにするライブラリーがあります。結論から申しますと、このライブラリーは絶対に使うべきではないライブラリーとなっています。

モダンな言語でHTML5を開発しよう! 俯瞰して理解するaltJSの比較 (前編 - TypeScript, CoffeeScript, Hexe) と題する記事があった。この記事は見出し中にある「HTML5を開発しよう」という言葉からして意味が通っていない。だが記事の内容から「HTML 5を始めとし、CSSやJavaScriptといったウェブ関連の技術を用いたアプリケーション作りをしよう」という意図であろうと類推することができる。しかしこの記事で問題なのはそのような重箱の隅を突くが如き枝葉末節な部分ではない。この記事の中で薦められているいわゆるaltJSと称される複数の言語たちではない、JavaScriptという言語はモダンな言語ではない、つまり近代的な言語ではないと断言してしまっていることである。 > ここ数年のHTML5やCSS3の劇的な進化に比べて、JavaScriptの言語としての進化は緩やかだったのではないでしょうか。HTML5の登場により、リッチなウェブサイト・コンテンツ・アプリケーションが求められる時代になったのに、それを制御する言語が未だレガシーなものであり、ニーズに追いついていないのが現状です。 先に引用した一文は前述した記事の第一段落に記された内容である。この短い一文の中に、事実誤認から来ているのであろう誤りが複数含まれてしまっている。このような記事は非常に度し難く、そして許すことができない。