2012-03-11 10 views
2

私は三つのファイルでウェブサイトがあります。window.onloadに関数を割り当てるときにスクリプトの順序が重要なのはなぜですか?

のindex.htmlを

<html> 
<head> 
<script src="First.js"></script> 
<script src="Second.js"></script> 
</head> 
<body></body> 
</html> 

First.js

window.onload = Main; 

Second.js

function Main() { var foo = 1; } 

ページを開くと、変数 'foo'が '1'に設定されていると思います。代わりに、私はページを開くと、それは壊れていることを示す'メインは定義されていません'と 'メイン()'が呼び出されることはありません。

ページが完全に読み込まれ、両方のスクリプトが読み込まれるまでウィンドウの '.onload'イベントが発生しない場合、なぜウィンドウオブジェクトに 'Main( ) 'メソッドを' Second.js 'に挿入しますか? 'Main()'はグローバルにアクセス可能な関数であるべきですか?

注:私はスクリプトをロードする順番を変更することができますし、私のコードはうまくいくはずですが、それは私の質問の目的ではありません。私が本当にやりたいことは、私の前提を立証することです。 Second.jsがロードされるまで

+0

2つのファイルを含める場所にHTMLファイルを投稿してください。 – Saebekassebil

答えて

2

<script>要素のコードは独立して順次とを実行しているので、それは動作しません(これは、デフォルトの同期スクリプトを想定しています)。すなわち、2つの異なる<script>セクションは、互いに前方参照することができません。さて、JavaScriptは同じコンテキスト内のの構造をホイストします。、これは単一の<script>で「順不同」だったでしょう。

前文/警告:

onloadを使用してないを考えてみましょう。それ以外のものが使用しようとすると(onload)、何かが壊れる可能性があります。 (私はjQueryを推奨しています。なぜなら、「これは正しい」と「とても簡単です」...そしてもう一度、他の多くのフレームワークもそうです。たとえば、1 :-)

を選んで、このjQueryのでは動作します:

jQuery(function() { Main() }) 

それが動作する理由の説明(とどのようにスクリプトを並べ替えたりjQueryのを使用せずにそれを修正する):

この場合、jQueryの内部イベントハンドラが呼び出され、匿名のコールバックが呼び出され、Main(これは現在、関数オブジェクトに解決されています)を呼び出します。ここで「類似」のコードは次のようになります。ある

window.onload = function() { Main() } 

これらの作業Mainため、すべての[同期] <script>要素が実行された場合にが発生たオンロードまでを評価しません。 (それはMainを評価するために何を意味するのかに関して、私のコメントを参照してください。)

を一方、window.onload = Main(またはjQuery(Main))をが右その後、Mainを評価し、その結果の値を使用します。他の人が指摘しているように、は、<script>要素の順序付けのために、この時点では設定されていません(「未定義です」)。

onload直接;-)

ハッピーコーディングを使用しない理由として一番上にノートを参照してください。

+0

私は、関数に等しい括弧に等しい変数を設定すると、評価するのではなく、単純に参照を格納すると信じています( 'var x = Main;'など)。 'Main()'を評価したい場合、 'var x = Main();'を実行します。それが正しいと仮定すると、 'window'オブジェクトの 'onload'に値を代入することにも同じことは適用されませんか?または、イベントへの割り当ては、割り当てられたものの評価を常にもたらすか? 'window.onload = Main;'の場合'Main()'を評価すると、 'window.onload = Main();'行う? – chopperdave

+0

@chopperdave Nope :)識別子は値に評価され、その値は式のどのオペランドとしても使用されます。例えば: '(functionName)()'と 'functionName()'は同じセマンティクスを持っています。最初の 'functionName'は* evaluate *され、結果の値には'() '(function-application)演算子が適用されます(厄介な例外を避けるためには関数オブジェクトでなければなりません)。前の式*(またはこの場合は 'functionName')を評価した結果であった* function-objectを呼び出す*(または呼び出し)は'() 'です。関数はJavaScriptのファーストクラスの値です。 –

+0

興味深いですが、私は実証するためにいくつかの例が必要だと思います。これをチャットに持って行くと、おそらく私たちはあなたの答えを明確にするために更新することができます。 – chopperdave

1

Main()機能が存在しないので、あなたはFirst.jsを読み込む場合、最初の(Mainが定義されていない)window.onload = Main;で使用するいかなる関数オブジェクトはありません。まだSecond.jsをロードしていない場合は、まずそれをロードします。

2

最初に2番目のスクリプトファイルを含める必要があります。関数が定義されています。ロードされない限り、最初のスクリプトで参照することはできません。

+0

これは私のコードをそのまま動作させる回避策ですが、それは私の質問の目的ではありません。目的は私の仮定が間違っている理由を理解することです。 – chopperdave

関連する問題