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

Posted

技术标签:

【中文标题】我可以为特定功能禁用 ECMAscript 严格模式吗?【英文标题】:Can I disable ECMAscript strict mode for specific functions? 【发布时间】:2011-08-26 14:01:56 【问题描述】:

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

我正在对我环境中的每个 javascript 文件调用 "use strict"。我所有的文件都是这样开始的

(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 是一个不可删除的道具,在检索时会抛出。所以我的问题是,是否有人知道 disable 更严格“功能方面”的方法?

"use strict"; 在被调用后被所有函数继承。现在我们可以通过调用顶部的"use strict"; 来在特定函数中使用严格模式,但是有没有办法实现相反的效果?

【问题讨论】:

您可以使用全局 eval 破解它以绕过严格模式 如果其他人需要知道这是怎么一回事:What does use strict do 我几乎希望这样的事情不存在。 “使用严格”的想法是向后兼容的选择加入策略。我不确定我是否喜欢向前向后兼容的想法,我们允许代码选择加入,然后允许代码的子部分再次选择退出。 你可以看这里>>just change .babelrc solution 【参考方案1】:

不,您不能为每个函数禁用严格模式。

了解严格模式在词法上工作很重要;意义——它影响函数声明,而不是执行。严格代码中声明的任何函数本身都成为严格函数。但并非任何从严格代码中调用的函数都一定是严格的:

(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

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

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

另请注意,indirect eval(由其他人建议)在这里不会真正有帮助。它所做的只是在全局上下文中执行代码。如果你尝试调用本地定义的函数,间接 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')();

)();

关于全局 eval 的混淆可能是因为全局 eval 可用于在严格模式下访问全局对象(不再简单地通过 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 创建的函数标记为严格。这不会发生在其他 strict-mode-supporting implementations(如 Chrome 12+、IE10、WebKit)中。

【讨论】:

如何将参数传递给偷偷摸摸的函数? 谢谢,我在 jasmine 单元测试中遇到了一个丑陋的问题,需要修改被测类使用的全局变量,但我无法做到。真棒作弊! @kangax,如果我使用的是严格模式,但我想动态禁用它。即,我将函数声明为严格,但在某些情况下,我不希望该函数严格,我想将函数更改为非严格。我应该做什么。?【参考方案2】:

(来自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 中似乎对我不起作用。我完全删除了对文件的严格说明以及错误处理方法所在的方法。我仍然会收到严格的错误。【参考方案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);

【讨论】:

以上是关于我可以为特定功能禁用 ECMAscript 严格模式吗?的主要内容,如果未能解决你的问题,请参考以下文章

ECMAScript 5 严格模式

JS基本概念

PHP 5 禁用严格标准错误

JavaScript严格模式(ECMAScript5新增)

可以为特定项目禁用 Qt 5.8 中的 QML 缓存吗?

js中的严格模式和非严格模式的比较