2007年12月18日(火)

« 【JavaScript】IE6でTABLE要素内をHTMLで書換える関数 | トップページ | 【JavaScript】これ(this)はなに? »

【JavaScript】function定義方法による動作の差異(覚書)

Javascriptで関数(function)を名前付きで定義したい場合、いろいろな書き方があります。
例えば、
  1. function TEST() {alert('TEST')}
  2. var TEST=function() {alert('TEST')};
  3. var TEST=function test() {alert('TEST')};
  4. var TEST=new Function("alert('TEST')");
といったもの。
これらは普段、特に意識して区別することなく使用しているのですが、調べてみると定義の仕方で微妙に動作が異なってくるようです(あ、new Function()は私には使いにくくてほとんど使っていないので検証はパス(苦笑))。
例えば→こんな感じ
上記のリンク先をIE6/Firefox/Operaで見てみると、それぞれ微妙に動作が異なってiいます(FirefoxとOperaは__parent__プロパティがあるかないかの違いだけなので、本質的なものではありませんが)。
もっとも顕著な違いとしては、
3.(右辺が名前付き関数)の書き方をしたあとで、右辺の関数名(例では'test')をtypeofしてみると、IE6ではfunction、Firefox/Operaではundefinedになる(IE6ではtest()で呼びだし可能、Firefox/Operaでは例外発生)。
ってことでしょうかね。
また、
IE6では、3.(右辺が名前付き関数)の前に 1.(通常の名前付き関数)の形式で 3. の右辺と同名の関数(例では'test')が定義されていると、3. によって上書きされてしまう。
という現象が発生してしまいます(サンプルの[CASE-2])。 2.のように右辺が無名関数になっていればそんな現象は起らないのですが、うっかり 3. のように右辺に関数名をつけて書いてしまうと、なかなか見つけにくいバグが発生しそうです。
ちなみに、Firefoxでは 3. の書き方をすると、TEST.__parent__が
({test:(function test() {p("TEST");})})
のように設定されます。
これから、まず新規に(無名の)Objectを作成し、そのプロパティ(上記例では'test')の値として右辺の関数を設定した後、当該プロパティ(への参照)を左辺に渡す、ということをやっているのではないかと推測されます。
実際、
var TEST=(function(){return {test:(function test() {p('TEST');})}.test;})();
あるいはもっとシンプルに
var TEST={test:function test() {p('TEST');}}.test;
のようにしてやっても、Firefoxでは 3. の場合と同様の動きになります。
これは 1. の書き方をした場合の関数の名前空間とは独立した名前空間を確保するため、かな?
多分、Operaでも似たようなことをしているのかとは思いますが、Operaは__parent__が無いため検証は出来ませんでした。
なお、FirefoxでTEST.__parent__を調べると、1./2.の場合には、windowオブジェクト(Global領域で定義された場合)もしくはnull(関数内で定義された場合)になります(名前空間用のObjectが新規に作成されるのは、1.~3.では3.のみ)。
右辺で名前付き関数を指定した場合、その都度専用の名前空間用オブジェクトが作成されてしまうことになるので(共用はされず、また同名にしても上書きにはならない模様)よほどの理由がない限り、無名関数とした方がよさそうです。

この記事をニフティクリップβに追加 この記事をはてなブックマークに追加 2007/12/18(火) 04:14 | | 記事の編集(管理者用)

風柳へひとこと(web拍手) 

パソコン・インターネット」カテゴリの記事

覚書」カテゴリの記事

トラックバック

この記事のトラックバックURL:

記事との関連性が薄いものやSPAM等、管理人が不適切と見なしたトラックバックについては予告無く削除する場合が有ります。悪しからずご了承下さい。

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/161784/17400578

この記事へのトラックバック一覧です: 【JavaScript】function定義方法による動作の差異(覚書):

コメント

コメントを書く