我可以为特定功能禁用ECMAscript严格模式吗?


76

我在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";的顶部调用而在特定功能中使用严格模式,但是有没有办法实现相反的目的?


您可以通过全局评估来破解它,以绕过严格模式
Raynos

1
如果其他人需要知道这是怎么回事:严格使用什么做
mplungjan 2011年

我几乎希望这样的事情不存在。“严格使用”是一种向后兼容的选择策略。我不确定我是否喜欢前向后向兼容的想法,即允许代码选择加入,然后允许子代码段再次选择退出。
2011年

您可以在这里看到>>只需更改.babelrc解决方案
hisland

Answers:


85

不,您不能禁用每个功能的严格模式。

重要的是要了解严格模式在词法上起作用;含义-它影响函数声明,而不是执行。在严格代码中声明的任何函数本身都会变成严格函数。但是,从严格代码中调用的任何函数都不一定是严格的:

(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)中不会发生这种情况。


如何将参数传递给偷偷摸摸的功能?
Szymon Toda 2014年

谢谢,我在茉莉花单元测试中遇到了一个丑陋的问题,需要修改被测类使用的全局变量,而我无法做到这一点。真棒作弊!
JuanguiJordán17年

@kangax,如果我使用严格模式,但我想动态禁用它。即,我声明一个函数为严格的,但在某些情况下,我不希望该函数为严格的,而我想将该函数更改为非严格的。我应该怎么做。
杰安斯(Jenyanth)'19

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

3

(来自http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/

(...)对于在严格函数体内调用的非严格函数,不执行严格模式(因为它们是作为参数传递的,或者是使用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)

...它应该工作。


在FF4中似乎不适用于我。我完全删除了文件及其错误处理方法所在位置的严格说明。我仍然会收到严格的错误。
jandy 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.