Firefox 3とFirebugで始めるJavaScript開発

第2回Firebugによるデバッグの基本、Console APIとその活用

さて、前回はインストールからFirebugのタブの基本的な部分について紹介をしてきました。今回は、Firebugに実装されているConsole APIの紹介と、Console APIを利用したデバッグ手法について解説していきます。

Firebugで利用できるAPI

Firebugには、デバッグに活用できる2つのAPIが実装されています。今回は、その2つあるAPIのうちConsole APIについて解説していきます。

Console API

Console APIはFirebugのタブだけでなく、コンテンツ側のJavaScriptから呼び出すことのできるAPIです。デバッグのために便利な関数があらかじめたくさん用意されています。これらの関数を以下に列挙しますので、目を通してください。

console.log(object[, object, ...])
渡された全てのオブジェクトをconsoleに出力します。また、第1引数を文字列にすることで、printf関数のように扱うことが出来ます。扱えるパターンは4種類あります。
  • %s:文字列
  • %d, %i:整数
  • %f:浮動小数点数
  • %o:オブジェクトへのリンク
console.debug(object[, object, ...])
基本的にはconsole.logと同じですが、エラーの行を表示します。
console.info(object[, object, ...])
基本的にはconsole.debugと同じですが、出力の先頭に「i」のアイコンをつけます。
console.warn(object[, object, ...])
基本的にはconsole.debugと同じですが、出力の先頭に「!」のアイコンをつけます。
console.error(object[, object, ...])
基本的にはconsole.debugと同じですが、出力の先頭に「×」のアイコンをつけ、ステータスバーのエラーに追加されます。
console.assert(expression[, object, ...]))
expressionがfalseなら第2引数以降をconsoleに出力する。第2引数以降はconsole.logと同様です。
console.dir(object)
渡されたオブジェクトのプロパティと値を全て出力します。
console.dirxml(object)
渡されたノードのソースツリーを表示します。HTMLタブと同様に表示され、クリックすることでHTMLタブで確認することができます。
console.trace()
この関数が呼び出された時点でのスタックトレースを出力します。
console.group(object[, object, ...});
console.groupEnd()が呼び出されるまでのconsoleの出力をグループ化します。引数はconsole.logと同様ですがその名前によってグループ化されるため、文字列を入れておけばよいでしょう。
console.groupEnd();
console.groupによるグループ化を終了します。
console.time(name[, reset])
console.timeEnd()が呼び出されるまでの実行時間を計測し、出力します。第2引数にtrueを渡すことによって時間をリセットする。
console.timeEnd(name)
console.timeによって計測されていた時間を出力します。console.timeで指定したものと同じ名前を指定する必要があります。
console.profile([title])
profile関数と同じく、console.profileEndが実行されるまでに実行された関数の解析を行います。
console.profileEnd()
console.profileによる解析を停止して結果を表示します。
console.count([title])
console.countが呼ばれた行が何回呼ばれたかをカウントし、出力します。引数にラベルを指定することができます。

console.logの基本を押さえる!

上記のように、Firebugで利用できるAPIにはたくさんのメソッドが用意されています。この中でも特に利用されるであろう、console.logの基本をここで確実に押さえておきたいと思います。console.logの挙動の理解度によってFirebugによるデバッグの速度は大きく変わってきますので、ここで確実に覚えておきましょう。

それでは、さっそくサンプルを交えつつ解説していきます。

オブジェクトの出力

まずは、console.logによってオブジェクトを出力させてみます。サンプルとしてYahoo! User Interface Library(通称、YUI)の基礎となるYAHOOオブジェクトを出力してみます。以下のコードを埋め込んだページを作成してください。

リスト1 ex.01.html(抜粋)
<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/yahoo-dom-event/yahoo-dom-event.js"></script> 
<script type="text/javascript">
console.log(YAHOO);
</script>

open(this.href);return false" onkeypress="window.open(this.href);return false">作成したページ(ex01.html)を読み込むと、console画面に出力がされます図1⁠。

図1 console.logの出力画面
図1 console.logの出力画面

さらに、出力された内容をクリックすると、次のようにDOMタブに切り替わります図2⁠。

図2 DOMの出力画面
図2 DOMの出力画面

このように、console.logによって出力されたものがオブジェクトの場合は、DOMタブでそのオブジェクトの中を確認することができます。

タブの遷移なしに確認をしたい場合はconsole.dirを使うといいでしょう。また、今回はconsole.logで例をあげましたが、行数を表示してくれるconsole.debugを利用するといいでしょう図3⁠。

図3 console.debugの行数表示
図3 console.debugの行数表示

その他の出力

console.logは渡されるオブジェクトの内容によって、出力のされかたが微妙に異なります。

ここでは代表的ないくつかの例を挙げてみます。先ほどのサンプルにscriptの中身に以下の赤字部分を追加し、body要素の中に"test"というID要素を持つHTMLを挿入してください。

リスト2 ex02.html(抜粋)
<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/yahoo-dom-event/yahoo-dom-event.js"></script> 
<script type="text/javascript">
console.log(YAHOO);
YAHOO.util.Event.on(window, "load", function() {
var String = "Yahoo! JAPAN"; // 文字列
var Func = function(str) { alert(str); }; // 関数
var Arr = new Array("Yahoo!", "JAPAN"); // 配列
var Dom = document.getElementById("test"); // HTML Element
console.debug(String);
console.debug(Func);
console.debug(Arr);
console.debug(Dom);
});
</script>

open(this.href);return false" onkeypress="window.open(this.href);return false">作成したページ(ex02.html)を読み込んでみてください。すると、文字列・関数・配列・HTML Element、それぞれの出力のされかたを確認することが出来ます図4⁠。

図4 文字列・関数・配列・HTML Elementの表示例
図4 文字列・関数・配列・HTML Elementの表示例

詳細の部分はそれぞれ、次のことを意味します。

文字列
文字列の場合は、文字列そのものをテキストで表示します。
関数
関数の場合は、Scriptタブの該当する関数の行へのリンクとして表示されます。
配列
配列の場合は、配列の一覧が表示されます。配列の各要素の中身は、中身のオブジェクトの内容ごとにそれぞれ最適な形で表示されます。
HTML Element
HTML Elementの場合は、HTMLタブの該当するHTMLの行へのリンクとして表示されます。また、右クリックより、HTMLのコピー、innerHTMLのコピー、XPathのコピー、そのHTMLに対するイベントの監視、そのHTMLを表示領域までスクロールする、DOMタブで表示、といったことを行うことができます図5⁠。
図5 HTML Elements
図5 HTML Elements

このように、渡される内容によってconsoleの出力やそこからたどれるものが大きく変わっていきます。Firebugによるデバッグの際、もっとも多様されるのがこのconsole.logを基本としたものとなると思います。

自分が書いたScriptにこれらを埋め込む場合は、デバッグの際に、もっとも最適なものが出力されるように考える必要があるため上記のような、基本的な部分はかならず抑えておきましょう。

log、debug、info、warn、errorを使い分ける

さて、これまではconsole.log、console.debugを使って紹介してきましたが、console.info、console.warn、console.errorでも基本的に表示される内容は同じです。

console.info、console.warnはそれぞれ、console.debugにアイコンがついただけですが、console.errorによって出力された場合はエラーとしてカウントが行われます。

リスト3 ex.03.html(抜粋)
<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript">
console.log(YAHOO);
console.debug(YAHOO);
console.info(YAHOO);
console.warn(YAHOO);
console.error(YAHOO);
</script>

open(this.href);return false" onkeypress="window.open(this.href);return false">作成したページ(ex03.html)を読み込むと、次の図のように表示されます図6⁠。

図6 log、debug、info、warn、errorそれぞれの表示
図6 log、debug、info、warn、errorそれぞれの表示

アイコンがつくことで出力されている内容がどのようなものなのか判別が行いやすくなるため、複数人による開発や、大規模なJavaScriptの開発時には、これらをつかいわけるといいでしょう。

また、上記の図の右下にも表示されていますが、重要な箇所にconsole.errorを仕込んでおくことでFirebugのウィンドウを閉じていても気づけるようになります。

いろいろなサイトで実際にconsole.logを使ってみよう!

さて、代表的なものをいろいろと紹介してきましたが、やはり身につけるための一番の近道は自分でいろいろと触ってみることです。

Firebugではconsoleタブから開いているページでのscriptの実行が行えるため、試しに様々なページを訪れ、いろいろなオブジェクトを調べてみましょう図7⁠。

図7 consoleタブからのconsole.logの実行例
図7 consoleタブからのconsole.logの実行例

console.timeでJavaScriptの実行時間を測定する

さて、ここではconsole.timeを使い、whlie文とfor文でそれぞれ1000回ループさせるのに、どちらがより高速かを調べてみましょう。以下のコードを埋め込んだページを作成してください。

リスト4 ex04.html(抜粋)
<script type="text/javascript">
var i;
console.time("while");
i=0;
while(i<1000){
        console.count();
        i++;
}
console.timeEnd("while");
console.time("for");
for(i=0;i<1000;i++){
        console.count();
}
console.timeEnd("for");
</script>

open(this.href);return false" onkeypress="window.open(this.href);return false">作成したページ(ex04.html)を読み込むと、同じ引数のconsole.timeとconsole.timeEndによって囲まれた部分の実行時間を測定してくれます。

実行すると、次のような結果が表示されます図9⁠。

図9 console.timeの結果表示
図9 console.timeの結果表示

図9のような結果だけ見るとwhile文のほうが速いことがわかります。しかし、JavaScriptはクライアントサイドで動くということもあり、環境や実行ごとにムラがあるため、正確に把握しようとするとリロードを繰り返して平均値を出さなくてはいけません。

そこで、console.profileを使って少し楽をしてみましょう。

console.profileを使って、関数ごとの実行時間を測定する

console.profileは、最初にも説明したとおり、console.profileEndが呼び出されるまでに実行された関数の解析を行います。以下のコードを埋め込んだページを作成してください。

リスト5 ex05.html(抜粋)
<script type="text/javascript">
console.profile();
function Func(){
        var i=0;
        while(i<1000){
                console.count();
                i++;
        }
};
function Func2(){
        for(var i=0;i<1000;i++){
                console.count();
        }
}
for(var i=0;i<10;i++){
Func();
Func2();
}
console.profileEnd();
</script>

基本的には前回のコードと同じですが、while文とfor文それぞれを関数化しました。また、コードの最初と最後にconsole.profileとconsole.profileEndを挿入しています。

実際にopen(this.href);return false" onkeypress="window.open(this.href);return false">作成したページ(ex05.html)を読み込むと、profileによる解析結果がconsoleタブに表示されます図10⁠。

図10 consoleの複数行入力
図10 consoleの複数行入力

最初に表示されているのは、すべての関数の実行時間の合計と合計呼び出し回数です。

詳細の部分はそれぞれ、次のことを意味します。

Function
関数の名前。匿名関数はprofileによって解析されないため注意してください。
Calls
その関数が呼び出された回数を表示します。今回の場合はそれぞれ10回ずつ関数が呼び出されているためどちらも10と表示されています。
Percent
その関数の実行時間の割合を表示します。
Own Time
その関数の実行にかかった時間の合計です。
Time
ネストされた関数も含めたその関数の実行時間の合計です。
Avg
その関数1回あたりの平均実行時間です。
Min
その関数1回あたりの最短実行時間です。
Max
その関数1回あたりの最長実行時間です。
File
その関数の場所を示します。

今回のような例の場合は、すべての値でFunc2が上回っているため、Firefox上ではfor文を使うよりもwhile文で回した方がわずかながら早い、ということが言えるようになります[1]⁠。

以上のようにconsole.proflieを使うと関数ごとに詳細な実行時間を出してくれるため、console.timeよりも詳細な解析を行うことができます。もちろん最初にも書いたとおり、console.profileは匿名関数などは解析の対象にならないため、そのあたりは工夫をしていく必要があります。

また、今回はwhile文とfor文のループの速度の比較のためにconsole.timeとconsole.profileを使いましたが、これまで説明してきた特性を理解すれば、もっと複雑な処理の際にどのような方法で実行速度を測定するのがもっとも適切かを判断できるようになると思います。

次回予告

さて、今回はFirebugに実装されているAPIの1つ、Console APIについて解説をしました。

次回は、もう1つのAPIである、Command Line APIと各タブごとについている細かい機能について解説していきたいと思います。

おすすめ記事

記事・ニュース一覧