ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript の eval()_javascript ヒントでの関数の使用に関する詳細な説明

JavaScript の eval()_javascript ヒントでの関数の使用に関する詳細な説明

WBOY
WBOYオリジナル
2016-05-16 19:02:331156ブラウズ

var func = eval("(function(){})");
alert(typeof func);
————————————
さらに問題は、 JScript と SpiderMonkey の名前付き関数の動作は、
十分に明確に説明されていません。この記事では、この問題について詳しく説明します。本の内容だけでなく、JS のより詳細な
説明と実行プロセスについても説明します。実際、すべての内容は本の中でカバーされています。しかし、分散しすぎているため、特定の問題を具体的に分析するのは不便です


まず第一に、表現と発言を明確にする必要があります。 JS の場合、eval() は常にステートメントの実行を試みるため、最初に実行テキストをステートメントとして
理解する必要があります。以下のように:
-----------
eval("1")
---------
JS の観点から見ると、eval() は次のようになります。ステートメントを実行すると、「1」は直接表現ではなくなり、「1;」と同等の直接表現文になります。これらの内容については、「5.2.2 動的実行時の文、式、値」
で詳しく説明します。

つまり、eval() の戻り値は、実際にはステートメントの最後の (有効な) 句の戻り値になります。次に、
「宣言文」と「式」を理解する必要があります。例:
────────
function x() {
//....
}
────────
明らかに、これは名前付き関数の「宣言文」です。「宣言文」は値を返さないことに注意してください。つまり、宣言ステートメントは構文解釈期間中にプリコンパイラーによって処理されますが、実行期間中は無意味です。
値も戻り値もありません。たとえば、単に「var」と指定すると、
値 (後者の値) が返されます。

上記のルールは JScript と SpiderMonkey で同じであり、違いはありません。違いは以下の
の内容です。まず、SpiderMonkey は、このような
機能を直接実装するために、「関数式」に含まれる「関数名」が無効であることを前提としています。 「関数名」は「宣言
文」に記述されており、「式」は文よりも一つ下のレベル(または下位レベル)であるため、「式
式」「文」内には記述できません。宣言」が表示されるため、式内の関数名を無視する必要があります。このように、SpiderMonkey では、次の
ステートメントが作成されます。
--------
x = "1234" (function
------)
機能さらに言うと、
--------
var X = 100;
x = "1234" (関数
これらの 2 行のコードでは、変数 X は2行目の関数名Xが不正なため書き換えました。これらの内容
については、書籍『5.4.2.1 文法文と文意味の不一致の問題』に詳しく解説されています。

MS JScript によるこの問題の処理についても、上のセクションで説明しています。 JScript は、コード本体
内の任意の場所に出現する関数識別子の宣言を認識します。つまり、上記の識別子は有効なので、グローバル変数
の「X」が書き換えられることになります。ただし、この理由から、JScript は次の問題を説明する必要があります:
----
eval("(function(){})");
eval("( function) SpiderMonkey は関数式を認識するため、両方の
を式のオペランドとして解釈します。また、JScript はコードの 2 行目にある変数名 X を認識する必要があるため、両方の
をステートメントとして解釈する必要があります。つまり、デフォルトでは、JScript は最初の行を匿名関数の「宣言ステートメント」とみなし、2 行目の
を名前付き関数の宣言ステートメントとみなします。したがって、前述したように、「宣言ステートメント」は値を返さないため、JScript のコードの両方の
行は未定義を返し、コードの 2 行目で変数名 X を宣言します。

この問題に関して、脚注で「関数宣言の文の意味」が確かに少し曖昧であると述べました。いずれにせよ、
だけは、JScript ではこれが「関数ステートメント宣言」であると考えられ、SpiderMonkey ではこれが「関数式
宣言」であると考えられるため、単純に理解する必要があります。

わかりました。これまでのところ、おそらく次のように明確に説明しただけです。
----
eval("(function(){})");
eval("(function X(){}) "); ;
------
これら 2 行のステートメントの効果とその理由。しかし、私の本の例と脚注についてはまだ疑問があります。これは次のテキストとコードから来ています:
————————
ただし、JScript には例外があります。関数リテラル (ここでは匿名関数) はこの方法では取得できません。たとえば、次のコード:
var func = eval("(function() { })");
// 出力は "未定義"
alert(typeof func); , 名前付き関数(*)を使用して取得できます。例: ………………
------
まず、このテキストは文脈依存であることに注意してください。変数「func」に有効な値を割り当てる方法を示したいだけです。これには
という 2 つのメソッドが含まれます:
-----
//メソッド 1、匿名関数を使用します
var func = eval("(function() { })"); (typeof func);

// 名前付き関数を使用します
var func;
alert(typeof func); 🎜>------
この部分の意味は、「JScript ではメソッド 1 (匿名関数を使用) を使用することはできません。2 番目のメソッドを使用する必要があります。」、
と脚注、SpiderMonkey はその逆であると言われており、この例のみを参照しています。SpiderMonkey では、2 番目のメソッドは無効ですが、最初のメソッドは有効です。

前の内容と若干異なるのは、メソッド 2 では「戻り値」を使用せず、 eval() ステートメント内の関数名宣言の効果のみを使用してグローバル変数 func に影響を与えることです。そして、それはまさに、SpiderMonkey がこの宣言の
識別子を認識しないためであり、無効です。

同じ理由で、読者 I22141 はこれを次のように変更すると言っています:
---- ----
SpiderMonkey では戻り値が使用されますが、これはもう同じではありません。上記の例のような問題。したがって、I22141
が尋ねた「(eval() を使用して SpiderMonkey で匿名関数を返すことができるが、名前付き関数は
のみ未定義を返すことができるということはどういう意味ですか?)」ということも、これとは乖離しています。質問例。

最後に、これは本には書かれていない、非常に奇妙な事件です。まず、
では、上で JScript で述べました:
--------
// 最初のケース
var func = eval("(function(){}) ");
alert(typeof func); // 「未定義」を表示
--------
ここで未定義と表示されるのは、JScript が次の関数を匿名関数宣言として解釈するためです。は価値がありません。実際、それは
よりも少し現実離れしています。それを変更しましょう:
————————————
// 2 番目のケース
var func = eval("(1, function(){})"); 🎜>alert (typeof func); // 表示「関数」
------
が異なります。では、最初のケースでは、なぜ JScript を式ではなく「宣言ステートメント」として理解する必要があるのでしょうか?よく分かりません。
--------
// 3 番目のケース
var X;
eval("(function X(){})");アラート(タイプさらに奇妙なのは、なぜ JScript が式演算子 "(...)" 内で "ステートメント" を許可するのかがわからないということです。理論的には、この状況
は文法解析で解釈するのが難しいからです。 「5.4.2.1 構文宣言と文の意味の不一致の問題」でも次のコードについて触れました:
---------
// 例 5: 構文宣言段階での書き換え
// 書き換え
(function Object(){
}).prototype.value = 100;

// 値を表示します
var obj = new Object(); >alert(obj.value);
--------
は、実行期間とステートメント解析期間中の「(X).prototype.value」の関数 X がグローバルをカバーしているためです。オブジェクト識別子
の機能は同じではありません。しかし、JScript が式で宣言ステートメントを許可する理由がまだわかりません。
これにさらに反するのは、そのような仮定が認められるのであれば、次のステートメントはなぜ実行できないのかということです:
---------
(var x=100 );
-------- 🎜>--------
ああ...この質問に対する最終的な答えについてはまだ混乱しています。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。