4

仕様(Annex C) によると、厳格モードのコードは、 name で識別子を割り当てる可能性のあるほとんど何もできません eval。実際の関数の使用を制限したい場合があることは理解できevalますが、名前の使用を制限することによってどのような目的が果たされるのかわかりませんか?

4

2 に答える 2

10

bobinceは基本的に正しいです。(私はMozillaのJSエンジンであるSpiderMonkeyに取り組んでおり、ES5のさまざまな部分を実装しており、時間の許す限りECMAScriptの議論に従います。)あなた(実装者と読者の両方)は本当にeval正規evalになりたいと思っargumentsています。arguments。厳密モードを使用すると、ほとんどこれを取得できます。

ただし、ここでのES5の制限は、望ましいほどではないことを指摘しておきます。まず、ボビンスをわずかに修正するために、厳密モードを使用してもeval、元のeval関数であるかどうかを確認することはできません。

"use strict";
this.eval = function() { return "ohai"; };
eval("7 + 10"); // "ohai"

これは、(JS愛好家の間で)よく知られているグローバルオブジェクトの間違いです。スクリプトは、名前を解決するために、スクリプト間で共有され、名前を付けたり変更したりできるグローバルオブジェクトを使用します。グローバル変数がバインドされているオブジェクトを参照できない場合は、この問題は発生しません。ES6は、常にスクリプト全体を対象とする別のオプトインシステム(おそらくMIMEタイプのように帯域外ですが、それはまだ不明です)を介してこれを修正する可能性があります。

ただし、名前を付けたり変更したりできるグローバルオブジェクトがなくても、strictモードは関数にスコープできるため、問題が発生します。

function outer()
{
  var eval = function() { return "kthxbai"; };
  function inner()
  {
    "use strict";
    return eval("2 + 5");
  }
  return inner();
}
outer(); // "kthxbai"

これらの問題は、strictモードが存在する場合でも存在し、ES6がグローバルオブジェクトを削除して無条件にstrictモード制限を適用する可能性があるため、早くてもES6まで解消されません。

したがってeval、厳密モードでは、評価されないことを参照できるという点で、まだ少し奇妙です。しかし、それを処理することは大したことではありません-実行時に実装は実際evalをチェックでき、それが失敗した場合は、構文がたまたま以外の名前を使用した場合と同じように実行しますeval。これには、のような式をeval(...)特別に処理する必要があります。evalしかし、静的に観察できない動作(ローカル変数と引数の変更、新しい変数の導入[厳密モードではファンがなくなりました-厳密モードの評価コードでの変数宣言は評価に対してローカルです)のため、とにかく良い実装はそれを行いましたコード]など)なので、実際の負担はありません。

これのどれもarguments偽の特別な形として当てはまらないことに注意する価値があります。関数スコープを介して厳密モードを使用している場合(この場合、その関数は外部スコープに割り当てられているのargumentsではなく表示されます)、またはグローバルスコープを介して使用している場合、特別な動作はありません。(グローバルストリクトモードコードでの変更を禁止するのはなぜですか?おそらく単純であり、開発者はどこでもそれらをより特別な形式として扱うように強制されますが、私にはわかりません。)argumentsargumentsarguments

于 2010-12-25T09:58:00.977 に答える
7

私は推測することしかできませんが、ES5-strictはそれを言ってevalおりarguments、識別子ではなく生の構文と見なされるべきであるように思われます。これらの2つの機能は、通常の機能では再現できない驚くべきファンキーマジックの動作を備えているため、構文レベルで実装する必要があります。

(特にeval、それを呼び出す関数でローカル変数に書き込む場合がありますarguments。に書き込むと、引数に対応するローカル変数の値が奇妙に変化します。この動作は厳密モードではなくなるようですが、ありがたいことに。)

互換性の理由から、ES5は実際に構文を作成することはできませevalarguments。したがって、彼らは可能な限り最も近いことをします。つまり、識別子argumentsは常にarguments魔法を参照し、識別子evalは常に排他的にeval魔法を参照します。

JSエンジンが関数に魔法が含まれているかどうかを確認できれば、最適化の可能性も向上する可能性があります。

于 2009-12-19T20:20:35.047 に答える