Javascriptでの関数宣言
Chrome17対応版AjaxIME Ajaxを使ってIMEを実現したAjaxIMEがFireFoxでは動くのに最新版のChromeで動かない。 動くように少しいじってみた。 Chrome17対応版AjaxIME 原因 Chromeで動かなかった原因はここ。 if(typeof getComputedStyle == 'undefined') { function getComputedStyle() { //中身は省略 } } FireFoxやChromeには getComputedStyle という関数が定義されているけど、 IEには定義されていない。 if文で有無を判定して、無い場合は動作をエミュレートする関数を定義している。 実行の様子をデバッガで追って見ると、Chromeではエミュレートする必要が無いのになぜか自前で定義した関数が呼び出されていた。 どうやら、Chromeでは 自作 getComputedStyle 関数が if文の中にあったとしてもコード読み込み時に作成されてしまうみたい。 FireFox だと if文の中が実行されない場合には作成されない。 結果だけ書くと、次のように書きなおしたら動いた。 if(typeof getComputedStyle == 'undefined') { getComputedStyle = function() { //中身は省略 } } あと Chrome だと、Input要素にフォーカスがあたった時に余計な装飾がついてしまうので、CSS上書きして抑制。 IE8でTextRangeが使えない問題は「IE8でのTextRange.moveToPoint()」を参考にして解決。 IE7のエミュレートモードにしているだけで、根本的な解決にはなってないけど、まあIEだしいいでしょ。 どっちが正しいの? とりあえず問題は解決したんだけど、FireFoxとChromeで動作が違うけど、どちらの動作が正しいの? 気になったので調べてみた。 「mixi Engineers’ Blog » 詳細 ECMA-262-3 第5章 関数」に関数の定義法についてわかりやすい解説が載っていた。 結論からいうと、一番初めの書き方は「誤り」で実際の動作は実装依存、つまり FireFox の動作も Chrome の動作も正しいとのこと。 関数定義と関数式 関数の定義法は大きく分けて、次のような関数定義と関数式に分かれている。 関数式は更に名前なしと名前付きがある。 //関数定義 function foo() { } //名前なしの関数式 var foo = function() { }; //名前付きの関数式 var foo = function _foo() { }; 普通の関数定義と無名関数があるのは知っててけど、単なるシュガーシンタックスみたいなものかと思った。 mixiのブログによると全くの別物。 関数定義と関数式の大きな違いは、実行時に呼び出し可能になっているかどうか。 関数定義は実行時に呼び出し可能になっているから、定義と呼び出しの順番は関係ない。