82

MDC または ECMAscript 仕様に関する私の質問については何も見つかりません。おそらく誰かがこれを解決するためのより「ハックな」方法を知っています。

私は"use strict"自分の環境内のすべての JavaScript ファイルを呼び出しています。私のファイルはすべてこのように始まります

(function(win, doc, undef) {
    "use strict";

    // code & functions
}(window, window.document));

これで、エラーを処理するカスタム関数ができました。その関数は、.callerプロパティを使用してコンテキスト スタック トレースを提供します。次のようになります。

var chain = (function() {
    var _parent = _error,
        _ret = '';

    while( _parent.caller ) {
        _ret += ' -> ' + _parent.caller.name;
        _parent = _parent.caller;
    }

    return _ret;
}());

しかしもちろん、strict モード.callerでは、取得時にスローされる削除不可能な prop があります。だから私の質問は、より厳密に「機能的に」無効にする方法を知っている人はいますか?

"use strict";呼び出された後、すべての関数に継承されます。これで、特定の関数の先頭で呼び出すだけ"use strict";で、厳密モードを使用できるようになりましたが、その逆を実現する方法はありますか?

4

3 に答える 3

96

いいえ、関数ごとに厳密モードを無効にすることはできません。

厳密モードは字句的に機能することを理解することが重要です。つまり、実行ではなく、関数の宣言に影響します。厳密なコード内で宣言された関数は、厳密な関数自体になります。しかし、厳密なコード内から呼び出される関数が必ずしも厳密であるとは限りません。

(function(sloppy) {
  "use strict";

   function strict() {
     // this function is strict, as it is _declared_ within strict code
   }

   strict();
   sloppy();

})(sloppy);

function sloppy(){
  // this function is not strict as it is _declared outside_ of strict code
}

厳密なコードの外で関数を定義し、それを厳密な関数に渡す方法に注意してください。

あなたの例で似たようなことをすることができます — 「ずさんな」関数を持つオブジェクトを持ってから、そのオブジェクトをその厳密に呼び出された関数に渡します。もちろん、「ずさんな」関数がメインのラッパー関数内から変数を参照する必要がある場合、それは機能しません。

また、他の誰かが提案した間接評価は、ここではあまり役に立たないことに注意してください。グローバルコンテキストでコードを実行するだけです。ローカルで定義された関数を呼び出そうとすると、間接評価はそれを見つけることさえできません:

(function(){
  "use strict";

  function whichDoesSomethingNaughty(){ /* ... */ }

  // ReferenceError as function is not globally accessible
  // and indirect eval obviously tries to "find" it in global scope
  (1,eval)('whichDoesSomethingNaughty')();

})();

グローバル eval に関するこの混乱は、おそらく、グローバル eval を使用して strict モード内からグローバル オブジェクトにアクセスできるという事実に由来します (これは、単に経由でアクセスすることはできthisなくなりました)。

(function(){
  "use strict";

  this; // undefined
  (1,eval)('this'); // global object
})();

しかし、質問に戻ります...

Functionコンストラクターを介して新しい関数をごまかして宣言することができます— これはたまたま厳密性を継承しませんが、(非標準の) 関数の逆コンパイルに依存し、外部変数を参照できなくなります

(function(){
  "use strict";

  function strict(){ /* ... */ }

  // compile new function from the string representation of another one
  var sneaky = Function('return (' + strict + ')()');

  sneaky();
})();

FF4+ は (私が知る限り) 仕様に同意していないようであり、作成された関数Functionを厳密と誤ってマークしていることに注意してください。これは、厳密モードをサポートする他の実装(Chrome 12+、IE10、WebKit など) では発生しません。

于 2011-05-18T02:14:02.950 に答える
5

( http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/より)

(...) 厳密モードは、厳密関数の本体内で呼び出される非厳密関数には適用されません (引数として渡されたか、 or を使用して呼び出されたためcall) apply

したがって、厳密モードを使用せずに別のファイルでエラー メソッドをセットアップし、次のようにパラメーターとして渡すと、次のようになります。

var test = function(fn) {
  'use strict';
  fn();
}

var deleteNonConfigurable = function () {
  var obj = {};
  Object.defineProperty(obj, "name", {
    configurable: false
  });
  delete obj.name; //will throw TypeError in Strict Mode
}

test(deleteNonConfigurable); //no error (Strict Mode not enforced)

...うまくいくはずです。

于 2011-05-16T16:26:40.417 に答える
3

代替手段は単にこれを行うことです

var stack;
if (console && console.trace) {
     stack = console.trace();
} else {
    try {
        var fail = 1 / 0;
    } catch (e) {
        if (e.stack) {
            stack = e.stack;
        } else if (e.stacktrace) {
            stack = e.stacktrace;
        }
    }
}
// have fun implementing normalize.
return normalize(stack);
于 2011-05-16T16:18:55.047 に答える