JavaScript 严格模式(Strict Mode)的几种开启方法及注意事项
我很惊讶地发现,JavaScriptworker
线程默认以非严格模式运行。这种情况应该很少发生,因为在使用 ES 模块 (ESM)、类或 “use strict “时,引擎会强制使用严格模式。我一开始并不知道这一点。我一直在使用 javascript-katas 软件仓库中用于本网站的 katas,它使用了 ESM 和 type=module
,这是我的默认设置。这使得整个 nodejs 项目、任何 npm …命令的运行都使用严格模式。要摆脱严格模式并不容易,但在非严格模式下运行代码的一种方法是使用worker 线程。
我总是喜欢了解事物的起源,所以让我们来了解一下严格模式。
严格模式–何时以及为何?
严格模式是在 ES5(2009 年)中引入的。在规范中,严格模式被添加为
为了安全起见,避免[……]认为容易出错的功能,加强错误检查
和
strict variant 还规定了必须通过抛出错误异常来报告的其他错误条件
因此,引入严格模式是为了让 JS 更安全。
严格模式(Strict Mode)?
实际上,我使用的 Worker 只是解决实际问题的一种手段,就是arguments
kata测试。为此,我需要在非严格模式下运行测试,所以我们来看看严格模式。
严格模式在哪里发挥作用?我一直在深入研究 “函数 API”,挖掘最早的 ES1 规范和之后的所有版本,以找出什么时候引入了什么,什么时候被弃用(JavaScript 中很少出现被弃用的情况)。因此,我在编写下面的测试时遇到了参数:
const fn = function() {
const arguments = 'arg';
return arguments;
}
assert.equal(fn('the argument'), 'arg');
测试失败的原因是 “Uncaught SyntaxError:Unexpected eval or arguments in strict mode”,这不是测试代码本身造成的,而是我在 Worker 线程中运行的其他代码造成的。上述测试仅被注入,并且只在 Worker 中运行了整个代码的一小部分。代码中有一个import
,导致所有代码都在严格模式下运行。正如错误提示的那样,严格模式下不允许使用arguments
。
因此,我想控制何时开启严格模式。为此,我们先来深入了解一下严格模式。
强制开启严格模式?
如上所述,”use strict “开启了严格模式,但在这种情况下,worker 代码中还没有严格模式,那么是什么开启了严格模式呢?在 ES6 规范的 “Strict Mode Code(严格模式代码)”一章中,新添加了以下几行来强制开启严格模式:
模块代码始终是严格模式代码。
ClassDeclaration 或 ClassExpression 的所有部分都是严格模式代码。
因此,import
打开了严格模式。
如何控制严格模式?
于是我重写了代码,不使用导入,这样就能在非严格模式下运行了。
现在我可以控制严格模式,只需在代码顶部添加 “use strict “即可。更妙的是,我可以在函数体的开头加上 “use strict”,这样就只能让这个函数以严格模式运行了。它必须是这个函数的第一条语句,请看下面的代码进行一些探索。哦,我看到新的katas 出现了。
'use strict'
const fn = function() {
const arguments = 'arg';
}
上述操作失败,并显示错误信息 “在严格模式下出现意外的eval
或arguments
“。
const fn = function() {
'use strict' // 在函数中使用 "use strict",测试仍然失败。
const arguments = 'arg';
}
上面的代码也失败了,原因相同。这里只有函数是在严格模式下运行的,但这也是使用arguments
的地方,所以失败了。
const fn = function() {
const arguments = 'arg';
}
'use strict' // 在函数开头不使用 "use strict "会被忽略,测试通过!
通过!
const fn = function() {
if (true) {
'use strict' 在作用域的开头使用 "use strict",而不在函数的开头使用 "use strict",则会被忽略,测试通过!
const arguments = 'arg';
}
}
这次也通过了,因为 “use strict “字符串不在函数开头。一开始我很恼火,因为我以为它会在作用域的开头,也就是{
之后,但我错了。规范也明确指出了这一点:
如果函数代码以包含使用严格指令的指令序言开始。
用人类的话说,这意味着函数必须以 “use strict “字符串开始。这里没有提及范围。规范还用非常难读的文字定义了另外三种情况。这三种情况是:1)全局代码;2)eval
代码;3)函数代码,当其中任何一种代码以 “use strict “字符串开头时,整个代码都将以严格模式运行。
由此,我不仅了解了严格模式的限制内容,还知道了如何控制严格模式。所有的神奇之处都不复存在了。
要开启严格模式,可以在所述的四种方式、类或模块中使用 “use strict”。这就是(手动)开启或强制开启严格模式的方法。