Hatena::Groupjavascript

JavaScriptで遊ぶよ

 | 

2010-10-06

withの中で関数定義

08:35

javascript:
with({hoge:'foo'}){
  alert(typeof hoge); /* これは自明 */
  function fuga(){
    alert(typeof hoge); /* ではこれは? */
  }
  fuga();
}

Firefox だと1つ目も2つ目も 'string' なんだけど、Chrome と Opera と Safari だと、2つ目が 'undefined'。

もし (function fuga() {alert(typeof hoge);})(); だったらどれも2回とも 'string' になる。

正しいのは Firefox だと思うけど…。


追記

コメント欄で指摘されたので試してみた。

javascript:
if(1){
  function hoge(){alert(1)}
}else{
  function hoge(){alert(2)}
}
hoge()

Firefox は1で、Opera、Chrome、Safari は2。

てっきり各ブラウザ「よろしく」やってくれてるのかと思ってた。

ConstellationConstellation2010/10/08 06:00超長いコメントで申し訳ないです...
function fuge() { }をSpiderMonkeyのようにFunctionStatementととる(ES5標準にはない)か, もしくはFunctionDeclarationととるかの違いです.
functionは本来, Blockなどの中に入れることが許されていない ( http://nanto.asablo.jp/blog/2005/12/10/172622 )のですが, それじゃあ不便なので, Firefoxのように,
var fuga = function fuga() {
alert(typeof hoge);
}
という(FunctionStatement)解釈をするか, それともFunctionDeclarationと解釈するかの違いがあります.
FunctionDeclrationなら関数Scopeにはいった瞬間に構築されるので後ろに定義があっても呼び出すことができますが, その代わりScopeとして設定されるのはその関数のLexicalEnvでwithですり替わったEnvではないです.
一方上記FunctionStatementの解釈でFunctionExpressionとして解釈されるならちょうどその位置まで来たときに構築され, Scopeとしてはwithですり替わったEnvが設定されます.
よってFirefox以外ではwithをたどらず, Firefoxのみwithをたどる感じです. そもそもFunctionStatement自体が厳格にはES5にないので, どっちも正しいという感じかもしれませんー.

edvakfedvakf2010/10/08 07:27FunctionStatement っててっきり ES5 で仕様になったのかと思ってました。Firefox だけ var fuga = function fuga() のように解釈するってのも知りませんでした。ありがとうございます。

if (window.addEventListener) {
function addEvent(...) {...}
} else {
function addEvent(...) {...}
}

みたいなのはどうなるんだろうか。(あとで試します)

長いコメント問題ないですよ。そのためにテキストエリア広げてありますから。

MillyMilly2011/04/27 03:54(fuga() {alert(typeof hoge);})(); になってますよ。function 抜けてます?

edvakfedvakf2011/04/27 04:24こっそり直しました。どうもありがとうございます。

トラックバック - http://javascript.g.hatena.ne.jp/edvakf/20101006
 |