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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6020178/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:54:34  来源:igfitidea点击:

Can I disable ECMAscript strict mode for specific functions?

javascriptecmascript-5ecma262strict-mode

提问by jAndy

I don't find anything about my question here on MDC or the ECMAscript specifications. Probably somebody knows a more 'hacky' way to solve this.

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

I'm calling "use strict"on every javascript file in my environment. All my files start like this

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

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

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

Now, I have a custom function which handles errors. That functions uses the .callerproperty to provide a context stack trace. Looks like this:

现在,我有一个处理错误的自定义函数。该函数使用该.caller属性提供上下文堆栈跟踪。看起来像这样:

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

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

    return _ret;
}());

But of course, in strict mode .calleris a non-deletable prop which throws when retrieved. So my question is, is anybody aware of way to disablestrict more "function-wise" ?

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

"use strict";is inherited by all functions after it was called. Now we have the possibilty to just use strict mode in specific functions by just calling "use strict";at the top of those, but is there a way to achieve the opposite ?

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

回答by kangax

No, you can't disable strict mode per function.

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

It's important to understand that strict mode works lexically; meaning — it affects function declaration, not execution. Any function declaredwithin strict code becomes a strict function itself. But not any function calledfrom within strict code is necessarily strict:

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

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

Notice how we can define function outside of strict codeand then pass it into the function that's strict.

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

You can do something similar in your example — have an object with "sloppy" functions, then pass that object to that strict immediately invoked function. Of course, that won't work if "sloppy" functions need to reference variables from within main wrapper function.

你可以在你的例子中做类似的事情——有一个带有“草率”函数的对象,然后将该对象传递给那个严格的立即调用的函数。当然,如果“草率”函数需要从主包装函数中引用变量,那将不起作用。

Also note that indirect eval— suggested by someone else — won't really help here. All it does is execute code in global context. If you try to call a function that's defined locally, indirect eval won't even find it:

另请注意,其他人建议的间接 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')();

})();

This confusion about global eval probably comes from the fact that global eval can be used to get access to global object from within strict mode (which isn't simply accessible via thisanymore):

关于全局 eval 的这种混淆可能来自这样一个事实,即全局 eval 可用于从严格模式中访问全局对象(不再简单地通过访问this):

(function(){
  "use strict";

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

But back to the question...

但是回到问题...

You can kind of cheat and declare a new function via Functionconstructor — which happens to not inheritstrictness, but that would rely on (non-standard) function decompilation and you would lose ability to reference outer variables.

你可以欺骗并通过Function构造函数声明一个新函数——这恰好没有继承严格性,但这将依赖于(非标准)函数反编译,你将失去引用外部变量的能力

(function(){
  "use strict";

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

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

  sneaky();
})();

Note that FF4+ seems to disagree with spec (from what I can tell) and incorrectly marks function created via Functionas strict. This doesn't happen in other strict-mode-supporting implementations(like Chrome 12+, IE10, WebKit).

请注意,FF4+ 似乎不同意规范(据我所知)并且错误地将通过创建的函数标记Function为严格。这不会发生在其他支持严格模式的实现中(如 Chrome 12+、IE10、WebKit)。

回答by Raynos

An alternative is simply doing this

另一种选择就是这样做

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

回答by Niloct

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

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

(...) Strict Mode is not enforced on non-strict functions that are invoked inside the body of a strict function (either because they were passed as arguments or invoked using callor apply).

(...) 在严格函数体内调用的非严格函数不强制执行严格模式(因为它们作为参数传递或使用callor 调用apply)。

So if you setup the error methods in a different file, without strict mode, and then pass them as a parameter, like this:

因此,如果您在不同的文件中设置错误方法,没有严格模式,然后将它们作为参数传递,如下所示:

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)

...it should work.

...它应该工作。