web-dev-qa-db-ja.com

返品後の可変巻き上げが一部のブラウザで機能するのに、機能しないのはなぜですか?

alert(myVar1);
return false;
var myVar1;

上記のコードは、IE、FF、およびOpera returnステートメントを関数に含める必要があることを示すエラーをスローします。ただし、SafariとChromeでは機能します(undefinedを示します)。

上記のコードはグローバルスコープで記述されています。すべての機能の外。

何らかの理由?

34
alter

JavaScriptでは、変数はスクリプトの先頭に移動されてから実行されます。だからあなたが実行するとそれはします

var myVar1;
alert(myVar1);
return false;

これは、javascriptが実際には字句スコープの真の意味を持っていないためです。これが、問題の原因となる巻き上げを防ぐために使用される領域の上部ですべての変数を宣言することがベストプラクティスと見なされる理由です。 JSLintはこれについてうめきます。

これはそれを説明する良い記事です http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

返品は無効です。真の巻き上げの例(上記のリンクから取得)を実行したい場合は、

var foo = 1; 
function bar() { 
    if (!foo) { 
        var foo = 10; 
    } 
    alert(foo); 
} 
bar();

これは10を警告します

コメント後に編集

以下は私の理解であり、どこかで読んだことがありますが、読んだすべての情報源を見つけることができないため、訂正の余地があります。

このアラートは、JavaScriptJITの違いによるものです。 TraceMonkey( http://ejohn.org/blog/tracemonkey/ )JavaScriptを使用して簡単な静的分析を実行し、次にJITを実行してから実行してみると思います。それが失敗した場合、明らかに何も機能しません。

V8は静的分析を行わず、JITに移動してから、何かを実行します。それはPythonにもっと似ています。 Chromeの開発者コンソール(Windowsではctrl + shift + j)でスクリプトを実行すると、エラーがスローされますが、アラートが表示されるように実行されます。

36
AutomatedTester

時々、巻き上げは間違った印象を与えるかもしれない方法で説明されます、すなわち、変数と関数は、以下のコードによって示されるように、実際には正しくない、物理的に上に移動されたかのようにJavaScriptエンジンによって巻き上げられます:

console.log(a);
var a = 'Hello World!';

コンソールに表示されるのは'Hello World'ではなくundefinedであるため、次のコードの動作が得られました。

var a;
console.log(a);
a = 'Hello World!';

の動作ではありません

var a = 'Hello World!';
console.log(a);

これは、変数と関数の宣言が最上位のステートメントに移動されていることから印象を受ける可能性があります。

しかし、JavaScriptは実際にはコードをどこにも移動していません。 JavaScriptの実行コンテキストを理解する必要があります。作成フェーズと実行フェーズの2つのフェーズがあります。作成段階では、これらの変数と関数のためにメモリスペースが作成され、人々はこのステップを巻き上げと混同しているようです。 JavaScriptは実際にはコードをどこにも移動していません。JavaScriptはすべてのコード用のメモリスペースを作成しました。つまり、変数と関数、関数は完全にメモリに配置できますが、変数の場合、割り当ては実行コンテキストの実行フェーズで処理されます。したがって、var a = 'Hello World!'を実行すると、JavaScriptエンジンは実行コンテキストの実行フェーズで実行を開始するときにaの値を認識するため、プレースホルダーが未定義になり、すべての変数が最初に未定義に設定されます。 JavaScriptで。したがって、巻き上げに頼って未定義を見るのは良くありません。したがって、コードの上に変数と関数を宣言することは常に良いことです。

17
user2603796

ECMA-262エディション3のセクション12.9(75ページ)には次のように記載されています。

ECMAScriptプログラムは、FunctionBody内にないreturnステートメントが含まれている場合、構文的に正しくないと見なされます。

つまり、関数の外側のreturn構文エラーです。 構文エラーが発生した場合、コードは実行されません。あなたが書いたかのようにあなたの例について考えてください:

alert(myVar1);
return false;
syntax error))))))))))))))))));

さらに、セクション16(157ページ)には次のように記載されています。

実装では、次の種類のランタイムエラーのインスタンスを構文エラーとして扱い、早期に報告する場合があります。

  • Return、break、continueの不適切な使用。

Firefoxのエンジンなど。 al。 (つまり、グローバルスコープでreturnを許可するJavaScript実装)mayは、次の句(同じセクション内)を想定して準拠している可能性がありますグローバルスコープでのreturnの実装定義を可能にします。

実装は、以下を除いて、指定されたとおりにすべてのエラーを報告するものとします。

  • 実装は、この仕様で説明されているもの以外に、追加のタイプ、値、オブジェクト、プロパティ、および関数を提供する場合があります。これにより、構成(グローバルスコープで変数を検索するなど)が、エラー(ReferenceErrorなど)をスローする代わりに、実装定義の動作をする可能性があります。
12
strager

このコードはほとんど意味がありません。

  • var myVar1は実行されません。
  • return false;関数に参加していないため、物を返しません

Opera、IEおよびFFはエラーをスローする権利があります。これは、関数内にいない限り戻ることができないため、このコードは実際には無効であるためです。

Safariで動作し、Chrome使用しているjavascriptエンジンがバグのあるコードを処理する準備ができているためである必要があります。「return」が表示され、ドロップされると思います。または、ある種のbreakに置き換えます。

関数の詳細: http://www.w3schools.com/js/js_functions.asp

3
marcgg

これはJavaScriptの巻き上げです。つまり、値を保持していない変数の値を出力しようとしています。

Javascriptは上記のコードを次のようにレンダリングします:-

var myVar1
alert (myVar1)
return false

さらに明確にするために、私はリンクjavascript hoistingを参照しました: http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

0
AugustRush