82

我在 MDC 或 ECMAscript 规范上找不到任何关于我的问题的信息。可能有人知道一个更“hacky”的方法来解决这个问题。

我正在调用"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;
}());

但是当然,在严格模式下.caller是一个不可删除的道具,在检索时会抛出。所以我的问题是,有没有人知道如何禁用严格的“功能明智”?

"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
}

请注意我们如何在严格代码之外定义函数,然后将其传递给严格的函数。

您可以在示例中执行类似的操作——拥有一个带有“草率”函数的对象,然后将该对象传递给该严格立即调用的函数。当然,如果“草率”的函数需要从主包装函数中引用变量,那将是行不通的。

另请注意,间接评估(由其他人建议)在这里不会真正有帮助。它所做的只是在全局上下文中执行代码。如果您尝试调用本地定义的函数,则间接 eval 甚至找不到它:

(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')();

})();

关于全局评估的这种混淆可能来自于全局评估可用于从严格模式(不再简单地通过)访问全局对象的事实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/

(...) 严格模式不会对在严格函数体内调用的非严格函数强制执行(因为它们作为参数传递或使用callor 调用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 回答