15

deletestrictモードで、が修飾されていない識別子で使用されたときに構文エラーが発生する理由を理解するのに問題があります。

ほとんどの場合、それは理にかなっています...varキーワードを使用して通常の方法で変数を宣言しdelete、それらを使用しようとすると、非厳密モードではサイレントに失敗するため、厳密モードで失敗するのは理にかなっていますそのような場合はエラーが発生します。

ただし、修飾された識別子を削除できない場合があります。

(function() {

  // "use strict";

  var obj = Object.create({}, { bloop: { configurable: false } });

  delete obj.bloop; // throws TypeError in strict mode, silently fails in non-strict.

  console.log('bloop' in obj); // true

}());

厳密モードでは、ここでランタイムチェックを実行する必要があります。これが発生すると、TypeErrorがスローされるためです。非厳密モードで非修飾識別子を正常に削除できる場合もあります...

// "use strict";

window.bar = 6;

console.log(typeof bar); // number

delete bar; // works in non-strict, syntax error in strict!

console.log(typeof bar); // undefined

実際、私の理解では、(非厳密モードで)削除できるかどうかは内部[[Configurable]]プロパティに依存し、修飾された識別子とは関係ありません。私の知る限り、厳密モードでは、(ローカルVOのプロパティとして)構成可能な非グローバル変数を削除する方法はありません。

(function() {

  // "use strict";

  eval('var foo = 5;');

  console.log(typeof foo); // number

  delete foo; // works in non-strict, SyntaxError in strict.

  console.log(typeof foo); // undefined

}());

だから、私の質問は、deleteプロパティが構成可能でない場合にTypeErrorがとにかくスローされるときに、修飾されていない識別子で使用するときにSyntaxErrorをスローすることのポイントは何ですか?これは不要な制限のようであり、場合によっては、厳密モードを使用しない以外に回避策がないように思われます(3番目の例)。この決定の背後にある動機を誰かが説明できますか?


eval更新:直接呼び出しには、呼び出し元の関数のスコープではなく、厳密モードで独自のスコープがあるため、3番目の例fooでは厳密モードでは定義されないという事実を見落としていることに気づきました。とにかく、ランタイムチェックはこれをキャッチしますが、副次的な質問が発生しますeval。非厳密の'd変数宣言の場合のように、構成可能なローカル変数を厳密モードにする方法はありませんか?の数少ない合法的な使用法の1つであるAFAIK eval

4

2 に答える 2

6

あなたはセクション11.4.1、パラグラフ5.aについて話している。スペックの:

  1. それ以外の場合、refは環境レコードバインディングへの参照であるため
    、a。IsStrictReference(ref)がtrueの場合、SyntaxError例外をスローします。
    b。バインディングをGetBase(ref)とします。
    c。GetReferencedName(ref)を引数として指定して、バインディングのDeleteBinding具象メソッドを呼び出した結果を返します。

あなたが「非修飾識別子」と呼んだものは、正式には「環境レコードバインディング」と呼ばれています。

さて、あなたの質問に。5.cのときにSyntaxErrorをスローする理由。とにかく失敗しますか?自分で答えたと思います!

厳密モードでは、ここでランタイムチェックを実行する必要があります。これが発生すると、TypeErrorがスローされるためです。

それは正しい。しかし、早く失敗する方が常に良いです。したがって、(解析時に) SyntaxErrorを検出する可能性がある場合は、その機会を利用する必要があります。

なんで?エラーが発生した場合にアプリを修正する手間を省くことができます。何時間ものデバッグではなく、すぐにエラーが表示される可能性のあるIDEについて考えてみてください。
また、このような制限は、最適化されたJITコンパイラーにとって有利な場合があります。

于 2012-08-19T08:41:32.457 に答える
3

厳密モードでオブジェクトを削除する場合。プロパティへのアクセスについて明示的に言及する必要があります。また、関数をどのように呼び出すかが重要であることに注意してください。new演算子が使用されていない場合thisは、の下で未定義でuse strictあり、以下の方法を使用することはできません。例:

「厳密に使用する」
関数func(){
  var self = this;
  self.obj = {};
  self.obj.x ='y'

  console.log(self.obj);
  self.objを削除//動作します
  //objを削除します//機能しません
  console.log(self.obj);
}

var f = new func();

関数(クロージャ)の外のオブジェクトを削除するには、次のように呼び出す必要があります

//上記と同じコード
f.objを削除します
于 2012-08-21T21:12:16.413 に答える