“use strict”在 JavaScript 中做了什么,背后的原因是什么?

javascript syntax jslint use-strict

最近,我通过 Crockford 的 JSLint 运行了一些 JavaScript 代码,它给出了以下错误:

第 1 行字符 1 的问题:缺少“use strict”语句。

做了一些搜索,我意识到有些人在他们的 JavaScript 代码中添加了 "use strict";。一旦我添加了语句,错误就停止出现了。不幸的是,谷歌没有透露这个字符串声明背后的大部分历史。当然,这一定与浏览器如何解释 JavaScript 有关,但我不知道会产生什么影响。

那么 "use strict"; 到底是什么,它意味着什么,它仍然相关吗?

当前的浏览器是否对 "use strict"; 字符串做出响应,或者它是否供将来使用?

这里的答案很旧,但它们是错误的。严格模式的主要原因不是为了防止编程错误——它是为了让 JavaScript 具有词法范围,以便可以静态分析:]

m
mikemaccana

ES6 模块更新

native ECMAScript modules(带有 importexport 语句)和 ES6 classes 中,严格模式始终处于启用状态且无法禁用。

原始答案

您可能会对这篇关于 Javascript 严格模式的文章感兴趣:John Resig - ECMAScript 5 Strict Mode, JSON, and More

引用一些有趣的部分:

严格模式是 ECMAScript 5 中的一项新功能,它允许您将程序或函数置于“严格”操作上下文中。这种严格的上下文会阻止执行某些操作并引发更多异常。

和:

严格模式有几个方面的帮助:它捕获一些常见的编码错误,抛出异常。当采取相对“不安全”的操作(例如获得对全局对象的访问权)时,它可以防止或引发错误。它禁用了令人困惑或考虑不周的功能。

另请注意,您可以将“严格模式”应用于整个文件......或者您只能将其用于特定功能(仍然引用 John Resig 的文章):

// Non-strict code...

(function(){
  "use strict";

  // Define your library strictly...
})();

// Non-strict code...

如果您必须混合旧代码和新代码,这可能会有所帮助;-)

所以,我想它有点像您可以在 Perl 中使用的 "use strict"(因此得名?):它通过检测更多可能导致损坏的事物来帮助您减少错误。

严格模式现在是 supported by all major browsers

P
Peter Mortensen

这是 ECMAScript 5 的一个新特性。John Resig 写了 a nice summary

它只是您放入 JavaScript 文件(文件顶部或函数内部)的字符串,如下所示:

"use strict";

现在将其放入您的代码中不会对当前浏览器造成任何问题,因为它只是一个字符串。如果您的代码违反了编译指示,将来可能会导致您的代码出现问题。例如,如果您当前有 foo = "bar" 而没有首先定义 foo,那么您的代码将开始失败......在我看来这是一件好事。

K
Kostas Minaidis

语句 "use strict"; 指示浏览器使用 Strict 模式,这是一种精简且更安全的 JavaScript 功能集。

功能列表(非详尽)

不允许全局变量。 (捕获缺少的 var 声明和变量名中的拼写错误)静默失败的分配将在严格模式下抛出错误(分配 NaN = 5;)尝试删除不可删除的属性将抛出(删除 Object.prototype)要求对象文字中的所有属性名称都是unique (var x = {x1: "1", x1: "2"}) 函数参数名称必须是唯一的 (function sum (x, x) {...}) 禁止八进制语法 (var x = 023; some devs错误地假设前面的零不会改变数字。)在严格模式下禁止 with 关键字 eval 不引入新变量 禁止删除普通名称(删除 x;) 禁止以任何形式绑定或分配名称 eval 和参数 Strict mode 不使用形参对 arguments 对象的属性进行别名。 (例如,在函数 sum (a,b) { return arguments[0] + b;} 中之所以有效,是因为 arguments[0] 绑定到 a 等等。)(请参阅下面的示例部分以了解区别)arguments.callee 是不支持

[参考:Strict modeMozilla 开发者网络]

例子:

严格模式代码不会为在其中创建的参数对象的属性设置别名

function show( msg ){
    msg = 42;
    console.log( msg );          // msg === 42
    console.log( arguments[0] ); // arguments === 42
}
show( "Hey" );

// In strict mode arguments[i] does not track the value of 
// the corresponding named argument, nor does a named argument track the value in the corresponding arguments[i]
function showStrict( msg ){
    "use strict";
    msg = 42;
    console.log( msg );          // msg === 42
    console.log( arguments[0] ); // arguments === "Hey"
}
showStrict( "Hey" );

11.的例子不清楚,不清楚严格模式有什么区别。

C
Community

如果人们担心使用 use strict,可能值得查看这篇文章:

ECMAScript 5 'Strict mode' support in browsers. What does this mean?
NovoGeek.com - Krishna 的博客

它讨论了浏览器支持,但更重要的是如何安全地处理它:

function isStrictMode(){
    return !this;
} 
/*
   returns false, since 'this' refers to global object and 
   '!this' becomes false
*/

function isStrictMode(){   
    "use strict";
    return !this;
} 
/* 
   returns true, since in strict mode the keyword 'this'
   does not refer to global object, unlike traditional JS. 
   So here, 'this' is 'undefined' and '!this' becomes true.
*/
A
Ataur Rahman Munna

提醒一句,你们这些强硬的程序员:将 "use strict" 应用于现有代码可能是危险的!这东西不是你可以在代码上贴上“更好”的感觉良好、快乐的表情贴纸。使用 "use strict" 杂注,浏览器会突然在它以前从未抛出过的随机位置抛出异常,因为在那个地方你正在做一些默认/松散的 JavaScript 很高兴允许但严格的 JavaScript 厌恶的事情!您可能在代码中很少使用的调用中隐藏了严格性违规,这些调用只会在它们最终运行时抛出异常 - 例如,在您的付费客户使用的生产环境中!

如果您打算冒险,最好将 "use strict" 与全面的单元测试和严格配置的 JSHint 构建任务一起应用,这将使您确信模块的任何黑暗角落都不会被可怕地炸毁只是因为您打开了严格模式。或者,嘿,这是另一种选择:只是不要将 "use strict" 添加到您的任何旧代码中,老实说,这样可能更安全。 绝对不要"use strict" 添加到您不拥有或维护的任何模块中,例如第三方模块。

我认为即使它是一种致命的笼中动物,"use strict" 也可以是好东西,但你必须做对。严格要求的最佳时机是当您的项目处于未开发阶段并且您从头开始时。将 JSHint/JSLint 配置为您的团队可以承受的所有警告和选项,获得像 Grunt+Karma+Chai 这样的良好构建/测试/断言系统,然后才开始将所有新模块标记为 "use strict" .准备好解决许多琐碎的错误和警告。如果 JSHint/JSLint 产生任何违规行为,通过将构建配置为 FAIL 来确保每个人都了解严重性。

当我采用 "use strict" 时,我的项目并不是一个新建项目。结果,我的 IDE 充满了红色标记,因为我的一半模块上没有 "use strict",而 JSHint 对此抱怨。这提醒了我将来应该做什么重构。我的目标是因为我缺少所有的 "use strict" 语句而不是红色标记,但那是几年后的事了。

s
sampathsris

使用“使用严格”;不会突然让你的代码变得更好。

JavaScript strict modeECMAScript 5 中的一项功能。您可以通过在脚本/函数的顶部声明它来启用严格模式。

'use strict';

当 JavaScript 引擎看到此指令时,它将开始以特殊模式解释代码。在这种模式下,当检测到某些可能最终成为潜在错误的编码实践时,就会引发错误(这是严格模式背后的原因)。

考虑这个例子:

var a = 365;
var b = 030;

由于痴迷于排列数字文字,开发人员无意中将变量 b 初始化为八进制文字。非严格模式会将其解释为值为 24(以 10 为基数)的数字文字。但是,严格模式会抛出错误。

有关严格模式下专业的非详尽列表,请参阅 this answer

我应该在哪里使用“使用严格”;?

在我的新 JavaScript 应用程序中:当然!当您对代码做一些愚蠢的事情时,严格模式可以用作举报人。

在我现有的 JavaScript 代码中:可能不是!如果您现有的 JavaScript 代码包含在严格模式下被禁止的语句,则应用程序将简单地中断。如果你想要严格模式,你应该准备好调试和纠正你现有的代码。这就是为什么使用'use strict';不会突然让你的代码变得更好。

如何使用严格模式?

插入“使用严格”;脚本顶部的语句: // 文件:myscript.js 'use strict';变量 a = 2; .... 请注意,文件 myscript.js 中的所有内容都将在严格模式下进行解释。或者,插入“使用严格”;函数体顶部的语句: function doSomething() { 'use strict'; ... } 函数 doSomething 的词法范围内的所有内容都将在严格模式下进行解释。词法作用域这个词在这里很重要。例如,如果您的严格代码调用不严格的库的函数,则只有您的代码在严格模式下执行,而不是被调用的函数。请参阅此答案以获得更好的解释。

严格模式下禁止哪些事情?

我发现一个 nice article 描述了严格模式下禁止的几件事(请注意,这不是一个详尽的列表):

作用域 从历史上看,JavaScript 一直对函数的作用域感到困惑。有时它们似乎是静态作用域的,但某些特性使它们表现得像动态作用域一样。这是令人困惑的,使程序难以阅读和理解。误解会导致错误。这也是性能的问题。静态作用域允许变量绑定在编译时发生,但动态作用域的要求意味着绑定必须推迟到运行时,这会带来显着的性能损失。严格模式要求所有变量绑定都是静态完成的。这意味着必须消除或修改以前需要动态绑定的功能。具体来说,取消了 with 语句,并且 eval 函数篡改其调用者环境的能力受到严格限制。严格代码的好处之一是 YUI Compressor 之类的工具在处理它时可以做得更好。隐含的全局变量 JavaScript 有隐含的全局变量。如果您没有显式声明变量,则会为您隐式声明一个全局变量。这使初学者更容易编程,因为他们可以忽略一些基本的家务活。但它使大型程序的管理变得更加困难,并且大大降低了可靠性。所以在严格模式下,不再创建隐含的全局变量。您应该显式声明所有变量。全局泄漏 有许多情况可能导致 this 绑定到全局对象。例如,如果在调用构造函数时忘记提供 new 前缀,则构造函数的 this 将意外绑定到全局对象,因此它不会初始化新对象,而是默默地篡改全局变量。在这些情况下,严格模式会将 this 绑定到 undefined,这将导致构造函数抛出异常,从而更快地检测到错误。嘈杂的失败 JavaScript 一直都有只读属性,但在 ES5 的 Object.createProperty 函数公开该功能之前,您无法自己创建它们。如果您尝试将值分配给只读属性,它将静默失败。赋值不会改变属性的值,但你的程序会继续进行,就好像它已经改变了一样。这是一种完整性风险,可能导致程序进入不一致的状态。在严格模式下,尝试更改只读属性将引发异常。八进制 在字长为 3 的倍数的机器上进行机器级编程时,数字的八进制(或以 8 为基数)表示非常有用。在使用字长为 60 位的 CDC 6600 大型机时需要八进制.如果您可以阅读八进制,您可以将一个单词视为 20 位数字。两位代表操作码,一位代表 8 个寄存器之一。在从机器代码缓慢过渡到高级语言的过程中,人们认为在编程语言中提供八进制形式是有用的。在 C 中,选择了一个非常不幸的八进制表示:前导零。因此,在 C 中,0100 表示 64,而不是 100,并且 08 是错误,而不是 8。更不幸的是,这种不合时宜的错误已被复制到几乎所有现代语言中,包括 JavaScript,它仅用于创建错误。它没有其他目的。所以在严格模式下,八进制形式不再被允许。等等 arguments 伪数组在 ES5 中变得更像数组了。在严格模式下,它会丢失其被调用者和调用者属性。这使得您可以在不放弃大量机密上下文的情况下将参数传递给不受信任的代码。此外,还消除了函数的参数属性。在严格模式下,函数字面量中的重复键会产生语法错误。一个函数不能有两个同名的参数。函数不能具有与其参数之一同名的变量。函数不能删除自己的变量。现在尝试删除不可配置的属性会引发异常。原始值不是隐式包装的。

未来 JavaScript 版本的保留字

ECMAScript 5 添加了保留字列表。如果将它们用作变量或参数,严格模式将引发错误。保留字是:

implements、interface、let、package、private、protected、public、static 和 yield

延伸阅读

严格模式 - JavaScript | MDN

浏览器支持严格模式

过渡到严格模式

W
Willi Mentzel

我强烈建议每个开发者现在就开始使用严格模式。有足够多的浏览器支持它,严格模式将合法地帮助我们避免我们甚至不知道您的代码中存在的错误。

显然,在初始阶段会有我们以前从未遇到过的错误。为了获得全部好处,我们需要在切换到严格模式后进行适当的测试,以确保我们已经捕获了所有内容。当然,我们不只是在我们的代码中抛出 use strict 并假设没有错误。因此,是时候开始使用这种非常有用的语言特性来编写更好的代码了。

例如,

var person = {
    name : 'xyz',
    position : 'abc',
    fullname : function () {  "use strict"; return this.name; }
};

JSLint 是由 Douglas Crockford 编写的调试器。只需粘贴到您的脚本中,它就会快速扫描代码中的任何明显问题和错误。

E
Ely

我想提供一个更有根据的答案来补充其他答案。我希望编辑最受欢迎的答案,但失败了。我试图使它尽可能全面和完整。

您可以参考 MDN documentation 了解更多信息。

"use strict" ECMAScript 5 中引入的指令。

指令类似于语句,但又有所不同。

use strict 不包含关键字:该指令是一个简单的表达式语句,由一个特殊的字符串文字(单引号或双引号)组成。没有实现 ECMAScript 5 的 JavaScript 引擎只会看到一个没有副作用的表达式语句。预计未来版本的 ECMAScript 标准会引入 use 作为真正的关键字;报价将因此变得过时。

use strict 只能用在脚本或函数的开头,即它必须在所有其他(实际)语句之前。它不必是函数脚本中的第一条指令:它可以在其他由字符串文字组成的语句表达式之前(并且 JavaScript 实现可以将它们视为特定于实现的指令)。跟在第一个真实语句(在脚本或函数中)之后的字符串文字语句是简单的表达式语句。解释器不得将它们解释为指令,它们没有效果。

use strict 指令指示以下代码(在脚本或函数中)是严格代码。当脚本包含 use strict 指令时,脚本最高级别的代码(不在函数中的代码)被视为严格代码。当函数本身以严格代码定义或函数包含 use strict 指令时,函数的内容被视为严格代码。当从严格代码调用 eval() 或包含 use strict 指令本身时,传递给 eval() 方法的代码被视为严格代码。

ECMAScript 5 的严格模式是 JavaScript 语言的一个受限子集,它消除了语言的相关缺陷,具有更严格的错误检查和更高的安全性。下面列出了严格模式和普通模式的区别(其中前三种尤为重要):

您不能在严格模式下使用 with 语句。

在严格模式下,所有变量都必须被声明:如果你给一个没有被声明为变量、函数、函数参数、catch-clause 参数或全局对象属性的标识符赋值,那么你将得到一个 ReferenceError。在正常模式下,标识符被隐式声明为全局变量(作为全局对象的属性)

在严格模式下,关键字 this 在作为函数(而不是方法)调用的函数中具有 undefined 值。 (在正常模式下,它总是指向全局对象)。这种差异可用于测试实现是否支持严格模式:

var hasStrictMode = (function() { "use strict"; return this===undefined }());

同样,当使用 call() 或 apply 以严格模式调用函数时,这正是 call() 或 apply() 调用的第一个参数的值。 (在正常模式下,null 和 undefined 被全局 Object 替换,并且不是对象的值被转换为对象。)

在严格模式下,当您尝试分配只读属性或为不可扩展对象定义新属性时,您将收到 TypeError。 (在正常模式下,两者都只是失败而没有错误消息。)

在严格模式下,将代码传递给 eval() 时,您不能在调用者的范围内声明或定义变量或函数(就像在正常模式下一样)。相反,为 eval() 创建了一个新范围,并且变量和函数都在该范围内。该范围在 eval() 完成执行后被销毁。

在严格模式下,函数的 arguments-object 包含传递给该函数的值的静态副本。在正常模式下,arguments-object 具有某种“神奇”的行为:数组的元素和命名的函数参数都引用相同的值。

在严格模式下,当删除运算符后跟非限定标识符(变量、函数或函数参数)时,您将收到 SyntaxError。在正常模式下,删除表达式什么都不做,并被评估为假。

在严格模式下,当您尝试删除不可配置的属性时,您将收到 TypeError。 (在正常模式下,尝试简单地失败并且删除表达式被评估为假)。

在严格模式下,当您尝试为对象字面量定义多个具有相同名称的属性时,它会被视为语法错误。 (在正常模式下没有错误。)

在严格模式下,当函数声明具有多个同名参数时,它被认为是语法错误。 (在正常模式下没有错误。)

在严格模式下不允许使用八进制文字(这些是以 0x 开头的文字。(在正常模式下,某些实现确实允许使用八进制文字。)

在严格模式下,标识符 eval 和 arguments 被视为关键字。你不能改变它们的值,不能给它们赋值,你不能将它们用作变量、函数、函数参数或catch块的标识符的名称。

在严格模式下,对检查调用堆栈的可能性有更多限制。 arguments.caller 和 arguments.callee 在严格模式下的函数中导致 TypeError。此外,当您尝试读取它们时,严格模式下函数的某些调用者和参数属性会导致 TypeError。

“在严格模式下,不允许使用八进制文字(这些文字以 0x ... 开头)”八进制文字以前导 0 开头。

S
Shubh

我的两分钱:

严格模式的目标之一是允许更快地调试问题。当某些错误的事情发生时,它会通过抛出异常来帮助开发人员,这可能会导致沉默和您网页的奇怪行为。我们使用 use strict 的那一刻,代码会抛出错误,帮助开发者提前修复它。

使用 use strict 后我学到的几件重要的事情:

防止全局变量声明:

var tree1Data = { name: 'Banana Tree',age: 100,leafCount: 100000};

function Tree(typeOfTree) {
    var age;
    var leafCount;

    age = typeOfTree.age;
    leafCount = typeOfTree.leafCount;
    nameoftree = typeOfTree.name;
};

var tree1 = new Tree(tree1Data);
console.log(window);

现在,此代码在全局范围内创建 nameoftree,可以使用 window.nameoftree 访问它。当我们实现 use strict 时,代码会抛出错误。

未捕获的 ReferenceError:未定义 nameoftree

Sample

删除 with 语句:

with 语句无法使用 uglify-js 等工具缩小。它们也是 deprecated 并从未来的 JavaScript 版本中删除。

Sample

防止重复:

当我们有重复的属性时,它会引发异常

未捕获的 SyntaxError:在严格模式下不允许对象文字中的重复数据属性

"use strict";
var tree1Data = {
    name: 'Banana Tree',
    age: 100,
    leafCount: 100000,
    name:'Banana Tree'
};

还有一些,但我需要获得更多的知识。

S
Stephen

如果您使用去年左右发布的浏览器,那么它很可能支持 JavaScript 严格模式。只有在 ECMAScript 5 成为当前标准之前的旧浏览器不支持它。

命令周围的引号确保代码在旧浏览器中仍然可以工作(尽管在严格模式下产生语法错误的东西通常只会导致脚本在旧浏览器中以某种难以检测的方式发生故障)。

P
Palec

添加 "use strict"; 时,以下情况将在脚本执行前抛出 SyntaxError

为未来的 ECMAScript 版本铺平道路,使用新保留的关键字之一(在 ECMAScript 6 之前):implements、interface、let、package、private、protected、public、static 和 yield。

在块中声明函数 if(a

八进制语法 var n = 023;

this 指向全局对象。函数 f() { "使用严格";这个.a = 1; }; F();

在对象字面量 {a: 1, b: 3, a: 7} 中为属性名称声明两次相同的名称在 ECMAScript 6 中不再是这种情况(错误 1041128)。

声明两个具有相同名称的函数参数 function f(a, b, b){}

将值设置为未声明的变量 function f(x){ "use strict";变量 a = 12; b = a + x*35; // 错误! } F();

对变量名使用 delete 删除 myVariable;

使用 eval 或 arguments 作为变量或函数参数名称“use strict”;论据++; var obj = { 设置 p(参数) { } };尝试 { } 捕捉(参数){ } 函数参数() { }

资料来源:

在 MDN 上转换为严格模式

MDN 上的严格模式

JavaScript 的严格模式以及为什么要在 Colin J. Ihrig 的博客上使用它(存档版)

使用 ECMAScript 2015,再次允许重复的属性名称!请参阅MDN documentation

a
alexyorke

严格模式对正常的 JavaScript 语义进行了一些更改:

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

修复了使 JavaScript 引擎难以执行优化的错误。

禁止某些可能在未来版本的 ECMAScript 中定义的语法。

如需更多信息,请访问 Strict Mode- Javascript

P
Peter Mortensen

“使用严格”;是程序员不会使用 JavaScript 松散或坏的属性的一种保险。它是一个指南,就像尺子会帮助你画直线一样。 “使用严格”将帮助您进行“直接编码”。

那些不喜欢使用标尺来直线直线的人通常会在那些页面中要求其他人调试他们的代码。

相信我。与设计不佳的代码相比,开销可以忽略不计。 Doug Crockford, who has been a senior JavaScript developer for several years, has a very interesting post here。就个人而言,我喜欢一直回到他的网站,以确保我不会忘记我的好习惯。

现代 JavaScript 实践应该总是唤起“使用严格”;语用。 ECMA 组将“严格”模式设为可选的唯一原因是允许经验不足的编码人员访问 JavaScript,并给他们时间适应新的和更安全的编码实践。

W
Willi Mentzel

从这一点开始,在所有敏感的 JavaScript 文件的开头包含 use strict 是成为更好的 JavaScript 程序员并避免随机变量成为全局变量和事情无声变化的小方法。

S
Shog9

Quoting from w3schools

“use strict”指令 “use strict”指令是 JavaScript 1.8.5(ECMAScript 版本 5)中的新指令。它不是语句,而是文字表达式,被早期版本的 JavaScript 忽略。 “使用严格”的目的是表明代码应该以“严格模式”执行。例如,在严格模式下,您不能使用未声明的变量。为什么是严格模式?严格模式使编写“安全”JavaScript 变得更容易。严格模式将以前接受的“错误语法”更改为真正的错误。例如,在普通 JavaScript 中,错误输入变量名会创建一个新的全局变量。在严格模式下,这将引发错误,从而不可能意外创建全局变量。在普通的 JavaScript 中,开发人员不会收到任何错误反馈,将值分配给不可写属性。在严格模式下,对不可写属性、getter-only 属性、不存在的属性、不存在的变量或不存在的对象的任何赋值都会引发错误。

请参阅http://www.w3schools.com/js/js_strict.asp了解更多信息

P
Palec

"use strict" 使 JavaScript 代码以 严格模式 运行,这基本上意味着一切都需要在使用前进行定义。使用严格模式的主要原因是避免意外全局使用未定义的方法。

同样在严格模式下,事情运行得更快,一些警告或静默警告会引发致命错误,最好总是使用它来制作更整洁的代码。

在 ECMA5 中广泛需要使用 "use strict"在 ECMA6 中它默认是 JavaScript 的一部分,因此如果您使用 ES6,则不需要添加它。

查看 MDN 中的这些陈述和示例:

“use strict”指令 “use strict”指令是 JavaScript 1.8.5(ECMAScript 版本 5)中的新指令。它不是语句,而是文字表达式,被早期版本的 JavaScript 忽略。 “使用严格”的目的是表明代码应该以“严格模式”执行。例如,在严格模式下,您不能使用未声明的变量。使用“use strict”的例子: 函数的严格模式:同样,要为函数调用严格模式,请输入确切的语句“use strict”; (或'use strict';)在任何其他语句之前的函数体中。

1) 函数中的严格模式

 function strict() {
     // Function-level strict mode syntax
     'use strict';
     function nested() { return 'And so am I!'; }
     return "Hi!  I'm a strict mode function!  " + nested();
 }
 function notStrict() { return "I'm not strict."; }

 console.log(strict(), notStrict());

2) 全脚本严格模式

'use strict';
var v = "Hi! I'm a strict mode script!";
console.log(v);

3)分配给不可写的全局

'use strict';

// Assignment to a non-writable global
var undefined = 5; // throws a TypeError
var Infinity = 5; // throws a TypeError

// Assignment to a non-writable property
var obj1 = {};
Object.defineProperty(obj1, 'x', { value: 42, writable: false });
obj1.x = 9; // throws a TypeError

// Assignment to a getter-only property
var obj2 = { get x() { return 17; } };
obj2.x = 5; // throws a TypeError

// Assignment to a new property on a non-extensible object.
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = 'ohai'; // throws a TypeError

您可以read more on MDN

F
FutureNerd

ECMAScript 委员会的一些人发表了一篇精彩的演讲:Changes to JavaScript, Part 1: ECMAScript 5" 关于如何增量使用 "use strict" 开关让 JavaScript 实现者能够清理 JavaScript 的许多危险特性,而不会突然破坏世界上的每个网站。

当然,它还谈到了这些错误功能中的很多(曾经)以及 ECMAScript 5 如何修复它们。

T
Tân

比较的小例子:

非严格模式:

for (i of [1,2,3]) console.log(i) // 输出: // 1 // 2 // 3

严格模式:

'使用严格'; for (i of [1,2,3]) console.log(i) // output: // Uncaught ReferenceError: i is not defined

非严格模式:

String.prototype.test = function () { console.log(typeof this === 'string'); }; '一个测试(); // 输出 // 假

String.prototype.test = function () { 'use strict'; console.log(typeof this === 'string'); }; '一个测试(); // 输出 // 真

O
Oriol

请注意,use strict 是在 EcmaScript 5 中引入的,此后一直保留。

以下是在 ES6ES7 中触发严格模式的条件:

如果全局代码以包含使用严格指令的指令序言开头(参见 14.1.1),则它是严格模式代码。模块代码始终是严格模式代码。 ClassDeclaration 或 ClassExpression 的所有部分都是严格模式代码。如果 Eval 代码以包含 Use Strict 指令的 Directive Prologue 开头,或者如果对 eval 的调用是包含在严格模式代码中的直接 eval(参见 12.3.4.1),则它是严格模式代码。如果相关的 FunctionDeclaration、FunctionExpression、GeneratorDeclaration、GeneratorExpression、MethodDefinition 或 ArrowFunction 包含在严格模式代码中,或者如果生成函数 [[ECMAScriptCode]] 内部槽值的代码以指令序言开头,则函数代码是严格模式代码包含使用严格指令。如果最后一个参数是一个字符串,作为参数提供给内置函数和生成器构造函数的函数代码是一个严格模式代码,该字符串在处理时是一个以包含使用严格指令的指令序言开头的 FunctionBody。

P
Pritam Banerjee

开发人员应该使用 "use strict" 的主要原因是:

防止意外声明全局变量。使用“use strict()”将确保变量在使用前用 var 声明。例如: function useStrictDemo(){ 'use strict'; //工作正常 var a = '没问题'; //不能正常工作并抛出错误 k = "problem" //即使这样也会抛出错误 someObject = {'problem': 'lot of problem'}; } 注意:“use strict”指令仅在脚本或函数的开头被识别。字符串“arguments”不能用作变量:“use strict”; var 参数 = 3.14; // 这将导致错误将限制关键字作为变量的使用。尝试使用它们会引发错误。

简而言之,这将使您的代码不易出错,进而使您编写出好的代码。

要了解更多信息,您可以参考 here

S
SethO

use strict 是一种使您的代码更安全的方法,因为您不能使用无法按预期工作的危险功能。而且,如前所述,它使代码更加严格。

j
jkdev

JavaScript “严格”模式是在 ECMAScript 5 中引入的。

(function() {
  "use strict";
  your code...
})();

在 JS 文件的最顶部写入 "use strict"; 会开启严格的语法检查。它为我们完成以下任务:

如果您尝试分配给未声明的变量会显示错误阻止您覆盖关键的 JS 系统库禁止一些不安全或容易出错的语言功能

use strict 也适用于单个函数。在您的代码中包含 use strict 始终是一种更好的做法。

浏览器兼容性问题:“使用”指令旨在向后兼容。不支持它们的浏览器只会看到一个没有被进一步引用的字符串文字。所以,他们会越过它并继续前进。

h
hologram

“使用严格”;是 ECMA 使 JavaScript 更健壮一点的努力。它引入了 JS 试图使其至少有点“严格”(其他语言自 90 年代以来实施严格的规则)。它实际上“迫使” JavaScript 开发人员遵循某种编码最佳实践。尽管如此,JavaScript 还是非常脆弱的。没有类型变量、类型方法等。我强烈建议 JavaScript 开发人员学习更健壮的语言,例如 Java 或 ActionScript3,并在 JavaScript 代码中实现相同的最佳实践,它会更好,更容易调试。

P
Pang

通常,JavaScript 不遵循严格的规则,因此增加了出错的机会。使用 "use strict" 后,JavaScript 代码应遵循与其他编程语言一样的严格规则集,例如终止符的使用、初始化前的声明等。

如果使用 "use strict",则应按照一组严格的规则编写代码,从而减少错误和歧义的机会。

W
Wesam

Use Strict 用于显示常见和重复的错误,以便对其进行不同的处理,并更改 java 脚本运行的方式,这些更改是:

防止意外的全局变量

没有重复

消除与

消除这种强制

更安全的 eval()

不可变的错误

您还可以阅读此article了解详细信息

A
Ashish

“使用严格”;定义 JavaScript 代码应该在“严格模式”下执行。

“use strict”指令是 ECMAScript 版本 5 中的新指令。

它不是语句,而是文字表达式,被早期版本的 JavaScript 忽略。

“使用严格”的目的是表明代码应该以“严格模式”执行。

例如,在严格模式下,您不能使用未声明的变量。

除 Internet Explorer 9 及更低版本外,所有现代浏览器都支持“使用严格”。

坏处

如果开发人员使用了严格模式下的库,但开发人员习惯于在正常模式下工作,他们可能会在库上调用一些无法按预期工作的操作。

更糟糕的是,由于开发人员处于正常模式,他们没有抛出额外错误的优势,因此错误可能会静默失败。

此外,如上所述,严格模式会阻止您执行某些操作。

人们通常认为你不应该首先使用这些东西,但是一些开发人员不喜欢这种约束,并且想要使用该语言的所有特性。

有关基本示例和参考,请通过:https://www.tutorialsteacher.com/javascript/javascript-strict

P
Pang

严格模式可以防止内存泄漏。

请检查以下以非严格模式编写的函数:

function getname(){
    name = "Stack Overflow"; // Not using var keyword
    return name;
}
getname();
console.log(name); // Stack Overflow

在这个函数中,我们在函数内部使用了一个名为 name 的变量。在内部,编译器将首先检查在该特定函数范围内是否有任何使用该特定名称声明的变量。由于编译器知道不存在这样的变量,因此它将检查外部范围。在我们的例子中,它是全局范围。同样,编译器理解在全局空间中也没有使用该名称声明的变量,因此它在全局空间中为我们创建了这样一个变量。从概念上讲,这个变量将在全局范围内创建,并在整个应用程序中可用。

另一种情况是,例如,变量在子函数中声明。在这种情况下,编译器会检查该变量在外部范围(即父函数)中的有效性。只有这样它才会检查全局空间并在那里为我们创建一个变量。这意味着需要进行额外的检查。这将影响应用程序的性能。

现在让我们在严格模式下编写相同的函数。

"use strict"
function getname(){
    name = "Stack Overflow"; // Not using var keyword
    return name;
}
getname();
console.log(name); 

我们会得到以下错误。

Uncaught ReferenceError: name is not defined
at getname (<anonymous>:3:15)
at <anonymous>:6:5

在这里,编译器抛出引用错误。在严格模式下,编译器不允许我们在未声明的情况下使用该变量。因此可以防止内存泄漏。此外,我们可以编写更优化的代码。

m
mishsx

严格模式消除了在非严格模式下会被忽略的错误,从而使 javascript “更安全”。

它是否被视为最佳实践?

是的,在使用 javascript 以包含严格模式时,它被认为是最佳实践的一部分。这是通过在您的 JS 文件中添加以下代码行来完成的。

'use strict';

在你的代码中。

这对用户代理意味着什么?

指示代码应在严格模式下解释,向浏览器等用户代理指定它们应按字面意思对待代码,并在代码没有意义时抛出错误。

例如: 考虑在您的 .js 文件中有以下代码:

场景 1:[无严格模式]

var city = "Chicago"
console.log(city) // Prints the city name, i.e. Chicago

场景 2:[无严格模式]

city = "Chicago"
console.log(city) // Prints the city name, i.e. Chicago

那么为什么在这两种情况下都会打印变量名呢?

如果没有打开严格模式,用户代理通常会对有问题的代码进行一系列修改,以试图使其有意义。从表面上看,这似乎是一件好事,事实上,在严格模式之外工作使得人们可以在没有完全确定所有细节的情况下使用 JavaScript 代码。但是,作为开发人员,我不想在代码中留下错误,因为我知道它以后可能会回来咬我,而且我也只想写出好的代码。这就是严格模式有帮助的地方。

场景 3:[严格模式]

'use strict';

city = "Chicago"
console.log(city) // Reference Error: asignment is undeclared variable city.

附加提示:要使用严格模式保持代码质量,您无需反复编写此代码,尤其是在您有多个 .js 文件的情况下。您可以在 eslint 规则中全局强制执行此规则,如下所示:

文件名: .eslintrc.js

module.exports = {
    env: {
        es6: true
    },
    rules : {
        strict: ['error', 'global'],
        },
    };
    

好的,那么在严格模式下会阻止什么?

在严格模式下使用变量而不声明它会引发错误。这是为了防止无意中在整个应用程序中创建全局变量。印刷芝加哥的例子特别涵盖了这一点。

删除变量、函数或参数是严格模式下的禁忌。 “使用严格”;函数 x(p1, p2) {};删除 x; // 这会导致错误

在严格模式下不允许重复参数名称。 “使用严格”;函数 x(p1, p1) {}; // 这会导致错误

Javascript 语言中的保留字不允许在严格模式下使用。这些词是implements interface、let、packages、private、protected、public。静态和产量

如需更全面的列表,请查看此处的 MDN 文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode

s
snnsnn

由于浏览器大战和管理不善,JavaScript 被匆忙设计和实施。结果,许多糟糕的设计决策、不直观的语法和混乱的语义都进入了语言。严格模式旨在修正其中一些错误。

但是在不创建替代解释的情况下修复这些错误会破坏向后兼容性。因此,"use strict" 指令在将代码传达给程序员时创建了代码的替代解释。

例如,this 关键字是指方法定义中的对象,如其他语言中的 thisself

let o = {
  name: 'John Doe',
  sayName: function(){
    console.log(this.name);
  }
};

o.sayName(); // 'John Doe'

this 在方法上下文之外没有任何用途,但所有 JavaScript 函数都有 this 关键字,无论它们是否是方法:

function run() {
  console.log(this);
}

run(); // Window

这里 this 解析为没有意义且没有任何用途的全局对象,因为全局对象已经在范围内可用。

在严格模式 this 中,全局函数解析为 undefined,这是我们所期望的。

"use strict"

function run() {
  console.log(this);
}

run(); // undefined

即使在严格模式下也无法修复一些错误,因为旧浏览器的语法应该是有效的,因为它们忽略了 "strict mode" 指令。这是设计使然。

A
Amin Azimi

严格模式在 v8 引擎中启用严格功能。一些功能的简短示例:

您可以通过编写全局启用它:

'use strict'; // strict mode enabled!

您只需包含在函数中的每个函数:

let myfunc = () => {
  'use strict'; // strict mode enabled
  
   b = 0; // broke
}

你必须在使用它之前声明一个变量(sane imo):

  var x;
  x = '0'; // ok
  y = '';  // not ok

启用了 es6 功能(这取决于浏览器),对于 node v4+,这很重要。

在某些情况下,性能会更好。

还有更多功能,请查看 here 了解更多信息!