14

このコードがエラーをスローするのはなぜですか?

// global non-strict code
(function eval () { 'use strict'; });

ライブデモ: http: //jsfiddle.net/SE3eX/1/

つまり、ここにあるのは名前付き関数式です。この関数式が非厳密なコードで表示されることを明示的に指摘したいと思います。ご覧のとおり、その関数本体は厳密なコードです。

厳密なモードのルールは次のとおりです:http ://ecma-international.org/ecma-262/5.1/#sec-C

関連する箇条書きはこれです(リストの最後の箇条書きです):

厳密なモードコード内で識別子evalまたは引数をFunctionDeclarationまたはFunctionExpressionの識別子として、または正式なパラメータ名(13.1)として使用するのはSyntaxErrorです。関数コンストラクター(15.3.2)を使用してこのような厳密モード関数を動的に定義しようとすると、SyntaxError例外がスローされます。

このルールがどのように適用されるかは、関数の宣言/式自体が厳密なコードで表示されている場合にのみ適用されることに注意してください。これは、上記の例では適用されませ

しかし、それでもエラーが発生しますか?なんで?

4

3 に答える 3

10

§13.1は、あなたのような場合に何が起こるべきかを概説しています:

  • 厳密モードのFunctionDeclarationまたはFunctionExpressionのFormalParameterList内で、識別子の値が複数回出現する場合は、SyntaxErrorです。
  • 識別子"eval"または識別子"arguments"が厳密モードFunctionDeclarationまたはFunctionExpressionの--FormalParameterList内で発生する場合、これはSyntaxErrorです。
  • 識別子"eval"または識別子"arguments"が厳密モードFunctionDeclarationまたはFunctionExpressionの識別子として発生する場合はSyntaxErrorです。

強調鉱山。strict-mode関数の識別子eval、したがって、SyntaxErrorです。ゲームオーバー。


上記が「厳密モードの関数式」である理由を確認するには、§13(関数定義)のセマンティック定義を参照してください。

プロダクション
FunctionExpressionfunction Identifier opt ( FormalParameterListoptFunctionBodyは次のよう に評価されます ) { }

  1. FormalParameterListoptで指定されたパラメーターと、FunctionBodyで指定されたbodyを使用して、13.2で指定された新しいFunctionオブジェクトを作成した結果を返します。実行中の実行コンテキストのLexicalEnvironmentをスコープとして渡します。FunctionExpressionが厳密なコードに含まれている場合、またはそのFunctionBodyが厳密なコードである場合は、trueをStrictフラグとして渡します。

強調鉱山。上記は、関数式(または宣言)がどのように厳密になるかを示しています。(平易な英語で)それが言うことは、FunctionExpressionstrict2つのシナリオにあるということです:

  1. コンテキストから呼び出されuse strictます。
  2. その関数本体はで始まりますuse strict

あなたの混乱は、実際には関数式全体がであるのに、関数本体だけがであると考えることから生じます。あなたの論理は直感的ですが、JSがどのように機能するかではありません。strictstrict


ECMAscriptがこのように機能する理由がわからない場合は、非常に簡単です。これがあるとしましょう:

// look ma, I'm not strict
(function eval() {
     "use strict";
     // evil stuff
     eval(); // this is a perfectly legal recursive call, and oh look...
             // ... I implicitly redefined eval() in a strict block
     // evil stuff
})();

ありがたいことに、関数式全体にとしてフラグが付けられているため、上記のコードはスローされstrictます。

于 2012-09-24T16:58:49.740 に答える
3

素晴らしい質問です!

したがって、問題の答えを見つけるには、実際に関数を宣言するプロセスを調べる必要があります(具体的には、ステップ3〜5-強調を追加)。

  1. ..。
  2. ..。
  3. envRecのCreateImmutableBinding具象メソッドを呼び出して、識別子の文字列値を引数として渡します。
  4. クロージャは、 FormalParameterList optで指定されたパラメーターと、 FunctionBodyで指定されたbodyを使用して、13.2で指定された新しいFunctionオブジェクトを作成した結果であるとします。funcEnvをスコープとして渡します。 FunctionExpressionが厳密なコードに含まれている場合、またはそのFunctionBodyが厳密なコードである場合は、trueをStrictフラグとして渡します。
  5. envRecのInitializeImmutableBinding具象メソッドを呼び出して、識別子とクロージャの文字列値を引数として渡します。

したがって、ステップ3でバインディングが作成された場合、evalの使用は問題になりませんが、ステップ5に達するとeval、厳密な字句環境内でのバインディングを初期化しようとします(つまり、に何かを割り当てますeval)。手順4に続く厳密なコンテキストにあるため、これは許可されていません。

制限は新しいeval変数の初期化ではないことに注意してください。これは、代入演算子のLeftHandSideExpressionとして使用されます。これは、関数宣言プロセスのステップ5で行われます。

アップデート:

@DavidTitarencoが指摘したように、これはセクション13.1で明示的にカバーされています(セクション13の暗黙の制限に加えて)。

于 2012-09-24T16:59:36.063 に答える
1

関数内でevalが関数自体を指しているため、エラーがスローされると推測しています。これは、厳密モードに違反しています。

于 2012-09-24T16:56:36.813 に答える