“严格模式”是什么,它如何使用?

146
我一直在查看Mozilla开发者网络上的JavaScript参考文档,我遇到了一个叫做“严格模式”的东西。我阅读了它,但我很难理解它的作用。有人能简要解释一下它的目的以及如何使用吗?

2
相关链接:https://dev59.com/ynM_5IYBdhLWcg3wiDuA - sampathsris
10个回答

157

它的主要目的是进行更多的检查。

只需在代码开头添加"use strict";,在任何其他内容之前即可。

例如,blah = 33; 是有效的JavaScript代码。它表示您创建了一个完全全局的变量blah

但在严格模式下,这是一个错误,因为您没有使用关键字 var 来声明变量。

大多数情况下,您不想在某个任意作用域中创建全局变量,因此大多数写blah = 33的时候都会出现错误,程序员实际上并不希望它成为全局变量,他们本意是写var blah = 33

它同样禁止了许多在技术上有效的操作。NaN = "lol"不会产生错误。它也不会改变NaN的值。使用严格模式,这样的(和类似的奇怪语句)会产生错误。大多数人会赞赏这一点,因为没有理由去编写NaN = "lol",所以最有可能是笔误。

在MDN页面上阅读更多关于严格模式的内容


4
这是 MDN 文档的完全副本。 - nkcmr
26
你对它的实用性有什么不理解的地方吗?它的目的是通过捕获有效但很可能存在错误的事物来帮助开发。 - Simon Sarris
“Using strict this” 是什么意思? - Peter Mortensen

35

在Simon的答案中没有提到的strict mode的一个方面是,在通过函数调用调用的函数中,strict mode会将this设置为undefined

因此像这样的东西:

function Obj() {
   this.a = 12;
   this.b = "a";
   this.privilegedMethod = function () {
      this.a++;
      privateMethod();
   };

   function privateMethod() {
     this.b = "foo";
   }
}

如果调用privateMethod时出现错误(因为无法向undefined添加属性),则会导致错误,而不是将b属性无用地添加到全局对象中。


4
需要添加 privateMethod.bind(this)(); 并使用 new 调用。jsbin.com - Artem P
严格模式下最重要的限制:https://learn.microsoft.com/en-us/scripting/javascript/advanced/strict-mode-javascript#restrictions-on-code-in-strict-mode - Krishna Mohan

23

为了使未来版本的语言更好地静态分析,添加了严格模式,它是ECMAScript的一个易于静态分析的子集。同时,严格模式的设计也希望限制自己使用严格模式的开发人员会犯更少的错误,并且他们所犯的错误会以更明显的方式表现出来。

Harmony将成为下一个主要版本的ECMAScript,它将基于ES5 strict构建。

Harmony建立在ES5严格模式之上,避免了太多的模式。

一些其他的语言实验也依赖于严格模式。 SES 依赖于ES5 strict模式的可分析性。

SES(安全ECMAScript)设计实验

通过删除或修复ES5 / Strict中的功能,设计对象能力编程语言。

应该可以直接从SES转换到ES5 / Strict。

标准的Annex C解释了严格模式和普通模式之间的区别。

严格模式的限制和异常
  • 标识符"implements"、"interface"、"let"、"package"、"private"、"protected"、"public"、"static"和"yield"在严格模式代码中被归类为FutureReservedWord令牌(7.6.12 [?])。
  • 遵循规范的实现,在处理严格模式代码时,不得扩展NumericLiteral(7.8.3)的语法,以包括OctalIntegerLiteral,如B.1.1所述。
  • 遵循规范的实现,在处理严格模式代码时(参见10.1.1),不得扩展EscapeSequence的语法,以包括B.1.2所述的OctalEscapeSequence。
  • 对未声明的标识符或其他无法解析的引用进行赋值不会在全局对象中创建属性。当在严格模式代码中发生简单赋值时,其LeftHandSide必须不能评估为一个无法解析的Reference。如果是,将抛出ReferenceError异常(8.7.2)。LeftHandSide也不能是对具有属性值{[[Writable]]:false}的数据属性的引用,对具有属性值{[[Set]]:undefined}的访问器属性的引用,或对内部属性[[Extensible]]的值为false的对象的不存在的属性的引用。在这些情况下,将抛出TypeError异常(11.13.1)。
  • 标识符eval或arguments不能出现在赋值运算符(11.13)或后缀表达式(11.3)的LeftHandSideExpression中,也不能作为前缀递增(11.4.4)或前缀递减(11.4.5)运算符操作的UnaryExpression。严格模式函数的Arguments对象定义了名为"caller"和"callee"的不可配置访问器属性,在访问时会抛出TypeError异常(10.6)。
  • 严格模式函数的Arguments对象不会动态共享其数组索引属性值与其函数的相应形式参数绑定。(10.6) 对于严格模式函数,如果创建了一个arguments对象,则将本地标识符arguments绑定到arguments对象是不可变的,因此可能不是赋值表达式的目标。(10.5)
  • 如果严格模式代码包含具有任何数据属性的多个定义的ObjectLiteral(11.1.5),则会引发SyntaxError。如果在严格代码中包含Identifier "eval"或Identifier "arguments"作为PropertySetParameterList中的Identifier,该PropertyAssignment包含在严格代码中,或者其FunctionBody是严格代码,则会引发SyntaxError(11.1.5)。
  • 严格模式eval代码不能在调用者的eval变量环境中实例化变量或函数。相反,将创建一个新的变量环境,并将该环境用于eval代码的声明绑定实例化(10.4.2)。
  • 如果在严格模式代码中评估this,则不会将其强制转换为对象。null或undefined的this值不会转换为全局对象,原始值也不会转换为包装对象。通过函数调用传递的this值(包括使用Function.prototype.apply和Function.prototype.call进行的调用)不会将传递的this值强制转换为对象(10.4.3、11.1.1、15.3.4.3、15.3.4.4)。
  • 在严格模式代码中出现delete运算符时,如果它的UnaryExpression是对变量、函数参数或函数名的直接引用,则抛出SyntaxError(11.4.1)。当在严格模式代码中发生删除运算符时,如果要删除的属性具

7

ECMAScript 5引入了“严格模式”的概念。

在代码中使用严格模式

严格模式适用于整个脚本或单个函数。它不适用于由{}括起来的块语句,试图将其应用于这些上下文将不起作用。

整个脚本:

假设我们正在创建app.js,则添加第一个语句"use script"将强制对整个代码使用严格模式。

// app.js whole script in strict mode syntax
“use strict”;
// Now you can start writing your code

函数的严格模式:

要为一个函数启用严格模式,需要在函数体的开头放置“use strict”语句,位于其他语句之前。

function yourFunc(){
    "use strict";

    // Your function code logic
}

严格模式包括对常规JavaScript语义的几个更改。首先,严格模式通过将一些JavaScript静默错误更改为抛出错误来消除这些错误。

例如:使用严格模式的代码

Enter image description here

在上面的代码示例中,如果不在代码中使用严格模式,则不会抛出错误。因为我们访问了未声明的变量x。所以在严格模式下访问未声明的变量会抛出错误。

现在让我们尝试在没有使用严格模式的情况下访问一个未声明的变量x。

(function(){
    x = 3;
})();

// Will not throw an error

使用严格模式的优势:

  • 通过抛出错误来消除JavaScript静默错误。
  • 修正错误,使得JavaScript引擎更容易进行优化。
  • 有时比相同的非严格模式代码运行得更快。
  • 禁止一些语法,这些语法可能在ECMAScript未来版本中被定义。

6

严格模式对正常的 JavaScript 语义进行了多项更改。

  • 严格模式通过将一些 JavaScript 静默错误更改为抛出错误来消除它们。

  • 严格模式修复了一些错误,这些错误使得 JavaScript 引擎难以执行优化。

  • 严格模式禁止一些语法,这些语法可能在未来的 ECMAScript 版本中定义。


2

2017年,我终于找到了文档:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode

严格模式是一种选择进入受限JavaScript变体的方式。 严格模式不仅仅是一个子集:它故意具有与正常代码不同的语义。 不支持严格模式的浏览器将以与支持严格模式的浏览器不同的行为运行严格模式代码,因此请不要在没有针对相关严格模式方面的支持进行功能测试的情况下依赖严格模式。 严格模式代码和非严格模式代码可以共存,因此脚本可以逐步选择进入严格模式。


严格模式对正常JavaScript语义进行了几个更改。首先,严格模式通过将一些JavaScript静默错误更改为抛出错误来消除它们。其次,严格模式修复了使JavaScript引擎执行优化变得困难的错误:严格模式代码有时可以比不使用严格模式的相同代码运行得更快。第三,严格模式禁止一些可能在ECMAScript的未来版本中定义的语法。


2

ECMAScript5引入了一些新的对象和属性,还有所谓的"严格模式"

严格模式是语言的一个子集,排除了已弃用的功能。严格模式是可选的,不是必需的,这意味着如果你想让你的代码在严格模式下运行,你需要在每个函数或整个程序中使用以下字符串(每个函数只需一次)来声明你的意图:

"use strict";

这不只是一个子集吗?比如检查未定义的变量? - Peter Mortensen

1

严格模式是 ECMAScript 5 中的新功能,允许开发者将代码放在“严格”上下文中。

这个严格上下文有助于开发者通过抛出更多异常来避免错误。

如何在 js 中使用严格模式?

很简单。只需将以下内容置于程序顶部即可在整个脚本中启用它:

"use strict";

或者将其放置在函数内部,以仅在该上下文中启用严格模式。

function imStrict(){
  "use strict";
  // … your code (executes in strict mode) …
}

使用JS的严格模式的优点

1. 块级函数作用域 作用域决定了代码中变量或其他资源的可见性或可访问性。

案例 I (非严格模式) enter image description here

案例 II (严格模式) enter image description here

2. 如果变量被赋值但未定义任何类型,则抛出错误/异常 enter image description here 在上面的示例中,“a”未声明任何值(let, const, var)。

3. 如果局部使用了保留变量,则会抛出错误 保留给未来JavaScript版本的关键字不能用作变量名,严格模式下会报错。

这些是: public implements interface let package private protected static yield 例如,enter image description here

4. 简单函数中的“this”在严格模式下指向“未定义”。 “this”关键字指的是调用函数的对象。 如果未指定对象,严格模式中的函数将返回undefined,普通模式中的函数将返回全局对象(window)。 以下是更好理解的示例

案例 I (非严格模式) enter image description here

案例 II (严格模式) enter image description here

5. 不允许删除变量(或对象)和函数。 enter image description here

6. 不允许重复参数名 enter image description here

默认情况下,类的主体在严格模式下执行。 例如:

class Rectangle {
//code executed here are in Strict mode
}

参考资料

  1. John Resig
  2. MDN
  3. W3School
以上是关于it技术的严格模式的参考资料。

0

关于如何使用严格模式的答案补充。如果您正在使用ES Modules,则代码始终在严格模式下运行,且无法禁用。因此,您不再需要在代码中使用"use strict"

以下是来自MDN的引用:

另外,请注意,与标准脚本中定义的脚本段相比,您可能会从模块内定义的脚本段中获得不同的行为。这是因为模块自动使用严格模式。


0

问题:

我遇到了以下问题。我正在按照教程进行操作,最终尝试编译以下 scss 文件并从中生成 CSS 代码。

.fatty{
  width: percentage(6/7);
}

使用以下的gulpfile.js任务:
var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('sass', function () {
    return gulp.src('app/scss/styles.scss')
        .pipe(sass())
        .pipe(gulp.dest('app/css'))
});

所以我得到的错误如下:

~/htdocs/Learning/gulp1/node_modules/gulp-sass/index.js:66
    let sassMap;
    ^^^

SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
// stacktrace here...

解决方案:

它向我展示了位于我的 gulp-sass 模块内部的 index.js 文件(基本上是锁定的,不应进行编辑)。但是,如果我强制在该 index.js 文件顶部添加 "use_strict",则可以顺利运行我的任务。

我感到无助,所以一直使用这个作为解决方案!但是,在查看了其他 Stack Overflow 问答 后,我看到了以下答案:

sudo npm install -g n
sudo n stable

当我更新了我的Node.js(到10.x版本),然后通过终端运行以下命令重新构建Gulp时,它告诉我:

npm rebuild node-sass --force

一切都没问题了。这就是解决方法。我撤销了对index.js Gulp.js模块文件所做的更改。现在一切运行顺利。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接