いいえ、関数ごとに厳密モードを無効にすることはできません。
厳密モードは字句的に機能することを理解することが重要です。つまり、実行ではなく、関数の宣言に影響します。厳密なコード内で宣言された関数は、厳密な関数自体になります。しかし、厳密なコード内から呼び出される関数が必ずしも厳密であるとは限りません。
(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 など) では発生しません。