“严格使用”在JavaScript中有什么作用,其背后的原因是什么?


7547

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

第1行第1个字符处的问题:缺少“使用严格”语句。

通过搜索,我意识到有些人将"use strict";其代码添加到了JavaScript中。添加语句后,错误停止出现。不幸的是,谷歌没有透露此字符串语句背后的许多历史。当然,它一定与浏览器如何解释JavaScript有关,但是我不知道会有什么影响。

那么到底是"use strict";什么,它意味着什么,并且仍然有意义?

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


5
这里的答案是旧的,但它们是错误的。严格模式的主要理由不是为了防止编程错误-而是使JavaScript在词法范围内,以便可以进行静态分析:]
Benjamin Gruenbaum

@BenjaminGruenbaum "use strict";单独使用不会使JS在词法范围内。使用let和声明变量也const应使用。
Koorosh Pasokhi

您正在混合使用块作用域和词汇作用域。
本杰明·格伦鲍姆

Answers:


4937

关于Javascript严格模式的这篇文章可能会让您感兴趣:John Resig-ECMAScript 5严格模式,JSON等

引用一些有趣的部分:

严格模式是ECMAScript 5中的一项新功能,可让您将程序或功能置于“严格”的操作环境中。这种严格的上下文会阻止采取某些措施,并引发更多异常。

和:

严格模式可以通过以下两种方式提供帮助:

  • 它捕获了一些常见的编码漏洞,并引发异常。
  • 当采取相对“不安全”的操作(例如获得对全局对象的访问权限)时,它可以防止或引发错误。
  • 它禁用令人困惑或考虑不周的功能。

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

// Non-strict code...

(function(){
  "use strict";

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

// Non-strict code... 

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

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

所有主要浏览器现在都支持严格模式。

本机ECMAScript模块(带有importexport语句)和ES6类中,严格模式始终处于启用状态,不能被禁用。


100
这么多年后更改默认值?为此,为时已晚:它会破坏这么多现有的站点/脚本/应用程序...唯一可能的事情是帮助将来更好地进行改进。
Pascal MARTIN

14
我尝试了一个小的代码段,该代码段"use strict"在Firefox 3.6,Safari 5,Chrome 7和Opera 10.6(所有Mac)中使用时无效。没有任何错误,所以我猜在任何浏览器中都不支持“严格使用”。没在IE9中测试过;)
赫斯基(Husky

11
快速更新:Firefox 4完全支持严格模式,据我所知,没有其他浏览器支持。Safari和Chrome具有“部分”支持,但我真的不知道这意味着什么。
Sasha Chedygov

29
Chrome 11和IE10似乎都通过了所有这些测试,即ie.microsoft.com/testdrive/HTML5/TryStrict/Default.html#
gman

12
@Julius-不能使用保留关键字来实现,因为这样,尝试触发严格模式的代码将在旧的浏览器中中断。添加“随机”字符串文字不会破坏任何内容。
nnnnnn 2014年

1245

这是ECMAScript 5的新功能。JohnResig撰写了一个不错的摘要

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

"use strict";

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


328
快速失败并大声失败。
Niels Bom

31
如果要在HTML文件中内联编写Javascript,请以开头每个新块<script>"use strict";。该标志仅适用于包含它的块。
nobar 2013年

7
有趣的是,这导致字符串必须带有单引号。所以写'use strict';代替
nilsi

1
那么javascript的提升概念将会怎样?
尼尔·夏尔马

1
@SunilSharma如果尝试提升,但由于未定义变量而失败,此刻它将把它添加到全局对象中。使用"use strict";,它将失败。这更有意义,因为如果将其添加到全局对象中,则意味着它可能在下次运行该函数时不起作用/进行其他操作来重置该块,因为它将位于最高块(全局)中。
wizzwizz4

646

该语句"use strict";指示浏览器使用严格模式,这是JavaScript的简化和安全功能集。

功能列表(非穷举)

  1. 禁止使用全局变量。(var在变量名中捕获缺少的声明和拼写错误)

  2. 静默失败的分配将在严格模式下抛出错误(分配NaN = 5;

  3. 尝试删除无法删除的属性将引发(delete Object.prototype

  4. 要求对象文字中的所有属性名称必须唯一(var x = {x1: "1", x1: "2"}

  5. 函数参数名称必须唯一(function sum (x, x) {...}

  6. 禁止使用八进制语法(var x = 023;某些开发人员错误地认为前面的零不会更改数字。)

  7. 禁止with关键字

  8. eval 在严格模式下不会引入新变量

  9. 禁止删除纯名(delete x;

  10. 禁止或名称的分配结合evalarguments以任何形式

  11. 严格模式不会arguments使用形式参数来别名对象的属性。(即,function sum (a,b) { return arguments[0] + b;}这在工作中是因为arguments[0]受约束a,依此类推。)

  12. arguments.callee 不支持

[参考:严格模式Mozilla开发人员网络 ]


40
Nit:允许使用全局变量,但必须明确(例如window.foo = bar)。
gcampbell

1
要求对象文字中的所有属性名称都是唯一的(var x = {x1:“ 1”,x1:“ 2”})是否有效
Arun Killu

4
您在11中的示例缺少对的修改(否则就没有意义)。即 函数sum(a,b){a = 0; 返回参数[0] + b; } alert(sum(1,2))由于混叠将返回严格模式3和严格模式2。
大卫·高斯曼

413

如果人们担心使用use strict它,那么值得阅读这篇文章:

浏览器中的ECMAScript 5“严格模式”支持。这是什么意思?
NovoGeek.com-克里希纳的博客

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

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.
*/

116
我不同意。我认为这说明了为什么它非常有用。从本质上讲,这意味着这将返回其功能,而不是window
Jamie Hutber

36
您什么时候想要this不适合使用的窗口window
Jamie Hutber

14
它指的是自己。this属于自己的职能,而不是全球范围的窗口
Jamie Hutber

26
在第二this个中,实际上是undefined
Broxzier

14
关键是您的JS程序将由于访问未定义的属性而开始失败,而不是在全局对象上进行无提示的操作。使跟踪细微的错误变得更加容易。
斯蒂芬·钟

208

提醒您,所有辛苦的程序员:应用于"use strict"现有代码可能很危险!这个东西不是一些让人感觉愉悦,表情愉快的标签,您可以在代码上拍一下以使其“更好”。有了这个"use strict"实用工具,浏览器会突然在从未发生过的随机位置抛出异常,这仅仅是因为在那个位置上您正在做一些默认/宽松的JavaScript允许但严格的JavaScript厌恶的事情!您可能会遇到严格的违规情况,这些隐匿在您的代码中很少使用的调用中,这些调用只会在最终运行时才会引发异常-例如,在付费客户使用的生产环境中!

如果您要尝试一下,最好将其"use strict"与全面的单元测试以及严格配置的JSHint构建任务一起应用,这将使您充满信心,认为模块的黑暗角落不会因为您已开启严格模式。或者,嘿,这是另一个选择:只是不添加"use strict"任何遗留代码,老实说,这样做可能更安全。 绝对不要添加"use strict"您不拥有或维护的任何模块,例如第三方模块。

我认为,即使这是一种致命的笼养动物,"use strict"也可以是好东西,但您必须正确地做。严格执行的最佳时间是当您的项目处于未开发状态并且从头开始时。配置JSHint/JSLint所有警告和选项,使您的团队可以紧紧抓住,并在安装时获得良好的构建/测试/声明系统Grunt+Karma+Chai,然后再将所有新模块标记为"use strict"。准备好解决许多小错误和警告。通过将构建配置为FAIL(如果JSHint/JSLint产生任何违规),确保每个人都了解重力。

当我采用该项目时,我的项目不是一个新建项目"use strict"。结果,我的IDE充满了红色标记,因为我没有"use strict"一半的模块,而JSHint对此表示抱怨。这让我想起了将来应该做的重构。由于所有遗漏的"use strict"陈述,我的目标是实现无标记的安全,但这距离现在还很遥远。


24
为什么开发人员会在此线程中使用“严格使用”?出于善意,它会在其他可以正常工作的JavaScript中抛出异常!只是像玉米片上的糖一样撒在代码上,是吗?没有!坏!应谨慎使用“严格使用”,最好仅在您控制的代码中通过针对所有主要浏览器的单元测试并使用所有代码路径的代码。你有考试吗?好的,“严格使用”对您来说很好,把自己淘汰掉。
DWoldrich

57
是。显然,“ use strict”可以破坏看似有效的javascript,而javascript以前从未破坏过。但是,之前没有破损的代码并不等于正确的代码以及应做的事情。通常,引用未声明的变量表示输入错误,等等。使用strict可以使您捕获此类错误,并希望在交付生产代码之前就可以捕获。
JosteinKjønigsen2015年

5
...或只是在代码的最后一次传递中应用“严格使用”,修正所有明显的问题,耸耸肩,说“足够好”,然后将其用于生产:)
Wolfie Inu 2015年

13
就我个人而言,我从未/很少添加 "use strict";到现有代码中。话虽这么说,我几乎总是使用它时,我从头开始编写新的代码
马丁

3
如果您已经在使用JSLint,则可能已经修复了大多数地方,“严格使用”会破坏事情。
乔纳森·

179

使用'use strict';不会突然使您的代码变得更好。

JavaScript的严格模式是一个功能的ECMAScript 5。您可以通过在脚本/函数顶部进行声明来启用严格模式。

'use strict';

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

考虑以下示例:

var a = 365;
var b = 030;

为了对数字文字进行排队,开发人员在不经意间将变量初始化b为八进制文字。非严格模式会将其解释为带有值的数字文字24(以10为底)。但是,严格模式将引发错误。

有关严格模式下的专业的详尽列表,请参见此答案


我应该在哪里使用'use strict';

  • 在我的 JavaScript应用程序中:绝对!当您对代码进行愚蠢的操作时,严格模式可以用作举报者。

  • 在我现有的 JavaScript代码中:可能不是!如果您现有的JavaScript代码具有在严格模式下禁止的语句,则应用程序将很容易崩溃。如果要使用严格模式,则应该准备调试和更正现有代码。这就是为什么使用'use strict';不会突然使您的代码变得更好的原因


如何使用严格模式?

  1. 'use strict';在脚本顶部插入一条语句:

    // File: myscript.js
    
    'use strict';
    var a = 2;
    ....

    请注意,文件中的所有内容都myscript.js将以严格模式进行解释。

  2. 或者,'use strict';在函数主体顶部插入一条语句:

    function doSomething() {
        'use strict';
        ...
    }

    函数的词法范围内的所有内容都doSomething将以严格模式进行解释。这个词词汇范围是很重要的位置。例如,如果您的严格代码调用非严格库的函数,则仅您的代码以严格模式执行,而不是被调用函数。请参阅此答案以获得更好的解释。


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

我找到了一篇不错的文章,描述了严格模式下禁止的几件事(请注意,这不是排他性清单):

范围

从历史上看,JavaScript对于函数的作用域一直感到困惑。有时它们似乎是静态作用域的,但是某些功能使它们的行为就像动态作用域一样。这令人困惑,使程序难以阅读和理解。误会导致错误。这也是性能问题。静态作用域将允许变量绑定在编译时发生,但是对动态范围的要求意味着必须将绑定推迟到运行时,这会带来很大的性能损失。

严格模式要求所有变量绑定都是静态完成的。这意味着必须消除或修改以前需要动态绑定的功能。具体来说,消除了with语句,并且eval函数篡改其调用者环境的能力受到严格限制。

严格代码的好处之一是,诸如YUI Compressor之类的工具 在处理代码时可以做得更好。

隐含全局变量

JavaScript隐含了全局变量。如果未显式声明变量,则会为您隐式声明全局变量。这使初学者更容易编程,因为他们可以忽略一些基本的家务劳动。但是,这使大型程序的管理更加困难,并且大大降低了可靠性。因此,在严格模式下,将不再创建隐式全局变量。您应该显式声明所有变量。

全球泄漏

在许多情况下,可能会导致this 绑定到全局对象。例如,如果您new在调用构造函数时忘记提供前缀,则构造函数this将意外绑定到全局对象,因此,与其初始化一个新对象,不如对它进行静默篡改全局变量。在这些情况下,严格模式将改为绑定thisundefined,这将导致构造函数抛出异常,从而允许更早地检测到错误。

嘈杂的失败

JavaScript一直具有只读属性,但是您无法自己创建它们,直到ES5的Object.createProperty 功能公开了该功能。如果尝试将值分配给只读属性,则它将静默失败。分配不会更改属性的值,但是您的程序将像执行该操作一样进行。这是完整性危害,可能导致程序进入不一致状态。在严格模式下,尝试更改只读属性将引发异常。

八进制

在字长为3的倍数的计算机上进行机器级编程时,数字的八进制(或基数8)表示非常有用。在使用CDC 6600大型机(字长为60位)时,您需要八进制数。如果您能读八进制,则可以将一个单词看成20位数字。两位数字表示操作码,一位数字标识8个寄存器之一。在从机器代码到高级语言的缓慢过渡期间,人们认为以编程语言提供八进制形式很有用。

在C语言中,选择了一个非常不幸的八进制表示形式:前导零。因此,在C语言中,它0100表示64,而不是100,并且08是错误,而不是8。更不幸的是,这种过时现象已被复制到几乎所有现代语言中,包括JavaScript,在其中它仅用于创建错误。它没有其他目的。因此,在严格模式下,不再允许使用八进制形式。

等等

参数伪数组在ES5中变得有点像数组。在严格模式下,它会丢失calleecaller 属性。这样就可以将您的arguments代码传递给不受信任的代码,而无需放弃很多机密上下文。而且,arguments功能的 性质被消除。

在严格模式下,函数文字中的重复键将产生语法错误。一个函数不能有两个具有相同名称的参数。函数不能具有与其参数之一相同名称的变量。函数不能delete拥有自己的变量。delete现在,对不可配置属性的尝试将 引发异常。原始值不会隐式包装。


将来的JavaScript版本的保留字

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

implementsinterfaceletpackageprivateprotectedpublicstatic,和yield


进一步阅读


2
这是一个很好的解释。但是,我有一个疑问,我可以结合其他Java脚本库(例如Angular js)使用“严格”模式吗?
UVM

3
@UVM:strict-mode指令仅影响词汇范围。即仅声明它的文件/功能。如果您有另一个没有'use strict'指令的文件/函数,则即使在严格模式下运行的函数调用它们,它们也将以非严格模式执行。请参阅请求以获取解释。
sampathsris '16

这并不完全正确。“严格使用”确实会改变代码的执行方式。
Cyber​​Ed

3
再看一遍,你是对的。我以为您的意思是它仅引发异常,但没有改变代码的工作方式(如更改this)。现在,我看到您指的是调用其他函数。
Cyber​​Ed '16

3
在某些情况下,八进制很有用。C语言的语法很可怕,但是我希望看到语言添加了新的八进制语法,然后可以弃用前导零形式。当然,对于Javascript支持前导零形式只是愚蠢的。
超级猫

138

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

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

例如,

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

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


6
@JamieHutber:请访问此链接caniuse.com/use-strict AND kangax.github.io/es5-compat-table。它将为所有浏览器提供确切的思路。
Pank

95

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

您可以参考MDN文档以获取更多信息。

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

指令与语句相似,但有所不同。

  • use strict不包含关键字:指令是一个简单的表达式语句,由特殊的字符串文字(单引号或双引号)组成。没有实现ECMAScript 5的JavaScript引擎只能看到一个没有副作用的表达式语句。预计将来的ECMAScript标准版本将use作为一个真正的关键词引入。这样一来,报价就会过时。
  • use strict只能在脚本或函数的开头使用,即它必须在所有其他(真实)语句之前。它不必是函数脚本中的第一条指令:它可以在其他由字符串文字组成的语句表达式之前(并且JavaScript实现可以将它们视为实现特定的指令)。字符串文字语句(在脚本或函数中)位于第一条真实语句之后,是简单的表达式语句。口译员不得将其解释为指令,并且它们无效。

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

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

  • 您不能with在严格模式下使用-statement。
  • 在严格模式下,必须声明所有变量:如果将一个值赋给尚未声明为变量,函数,函数参数,catch-clause参数或global属性的标识符,Object则将获得ReferenceError。在正常模式下,标识符隐式声明为全局变量(作为global的属性Object
  • 在严格模式下,关键字在作为函数(而不是方法)调用的函数中this具有值undefined。(在正常模式下,this始终指向global Object)。此差异可用于测试实现是否支持严格模式:
var hasStrictMode = (function() { "use strict"; return this===undefined }());
  • 同样,当使用call()apply在严格模式下调用this函数时,call()apply()调用的第一个参数的值也正是该值。(在普通模式下nullundefined被全局Object对象和不是对象的值替换为对象。)

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

  • 在严格模式下,将代码传递给时eval(),您不能在调用方的范围内声明或定义变量或函数(就像在常规模式下那样)。而是为它创建一个新范围,eval()并且变量和函数都在该范围内。eval()执行完成后,该作用域被销毁。
  • 在严格模式下,函数的arguments对象包含值的静态副本,这些值将传递给该函数。在正常模式下,arguments-object的行为有些“神奇”:数组的元素和命名的函数参数都引用相同的值。
  • 在严格模式下,SyntaxErrordelete运算符后跟非限定标识符(变量,函数或函数参数)时,您将获得。在正常模式下,delete表达式将不执行任何操作,并被评估为false
  • 在严格模式下,TypeError当您尝试删除不可配置的属性时会得到一个“ a”。(在正常模式下,尝试仅会失败,并且delete表达式的计算结果为false)。
  • 在严格模式下,当您尝试为对象文字定义名称相同的多个属性时,将其视为语法错误。(在正常模式下没有错误。)
  • 在严格模式下,当函数声明具有多个具有相同名称的参数时,将其视为语法错误。(在正常模式下没有错误。)
  • 在严格模式下,不允许使用八进制文字(这些文字以0x。开头(在正常模式下,某些实现确实允许使用八进制文字。)
  • 在严格模式下,标识符evalarguments被视为关键字。您不能更改它们的值,不能给它们分配值,也不能将它们用作变量,函数,函数参数或catch块标识符的名称。
  • 在严格模式下,对检查调用堆栈的可能性有更多限制。arguments.callerarguments.callee导致TypeError严格模式下的功能。此外,在严格模式下,函数的某些调用方和参数属性会TypeError在您尝试读取它们时引起。

4
“在严格模式下,不允许使用八进制文字(这些文字以0x开头...)。”八进制文字以Lead开头0
Alex Gittemeier '16

83

我的两分钱:

严格模式的目标之一是允许更快地调试问题。当某些错误的事情发生时,它会引发网页异常的异常行为,从而引发异常,从而有助于开发人员。我们使用的那一刻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之类的工具缩小语句。它们也已弃用,并从将来的JavaScript版本中删除。

Sample

防止重复:

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

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

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

很少,但是我需要获得更多的知识。


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

62

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

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


12
那怎么办呢?
阿尼什·古普塔

7
……这部分描述了兼容性,但没有实际描述兼容性。
courtsimas 2012年

58

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

  • 从而为未来的ECMAScript版本的方式,使用新的保留关键字之一(预知的ECMAScript中6): ,implementsinterfaceletpackageprivateprotectedpublicstaticyield

  • 块中声明功能

    if(a<b){ function f(){} }
  • 八进制语法

    var n = 023;
  • this 指向全局对象。

     function f() {
          "use strict";
          this.a = 1;
     };
     f(); 
  • 在对象文字中为属性名称声明两次相同的名称

     {a: 1, b: 3, a: 7} 

    ECMAScript 6(错误1041128)不再是这种情况。

  • 声明两个具有相同名称函数的函数参数

    f(a, b, b){}
  • 为未声明的变量设置值

    function f(x){
       "use strict";
       var a = 12;
       b = a + x*35; // error!
    }
    f();
  • 使用delete一个变量名delete myVariable;

  • 使用evalarguments作为变量或函数参数名称

    "use strict";
    arguments++;
    var obj = { set p(arguments) { } };
    try { } catch (arguments) { }
    function arguments() { } 

资料来源:


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

53

严格模式对常规JavaScript语义进行了几处更改:

  • 通过将它们更改为引发错误来消除一些JavaScript静默错误。

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

  • 禁止在将来的ECMAScript版本中定义某些语法。

有关更多信息,请访问严格模式-Javascript


52

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

那些不喜欢使用标尺直行的人通常会出现在这些页面中,要求其他人调试其代码。

相信我。与设计不良的代码相比,开销可忽略不计。多年担任高级JavaScript开发人员的Doug Crockford在此发表了一篇非常有趣的文章。就个人而言,我喜欢一直回到他的网站,以确保我不会忘记自己的良好做法。

现代JavaScript实践应始终唤起“使用严格”的原则;实用 ECMA集团将“严格”模式设为可选的唯一原因是,允许经验不足的编码人员访问JavaScript,然后给予时间以适应新的更安全的编码实践。


66
严格模式是可选的原因与您所说的无关。真正的原因是不要破坏可能不符合要求的现有代码
Dexygen

17
确实,经验不足的编码员应该是一个启用“严格使用”的编码员。
Antti Haapala 2014年

46

use strict从这一点开始,在所有敏感的JavaScript文件的开头都包含一个小方法,可以成为一个更好的JavaScript程序员,并避免随机变量成为全局变量并避免静默改变。


42

从w3schools报价

“严格使用”指令

“严格使用”指令是JavaScript 1.8.5(ECMAScript版本5)中的新增功能。

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

“使用严格”的目的是指示应在“严格模式”下执行代码。

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

为什么选择严格模式?

严格模式使编写“安全” JavaScript更加容易。

严格模式将以前接受的“错误语法”更改为实际错误。

例如,在普通的JavaScript中,错误输入变量名称会创建一个新的全局变量。在严格模式下,这将引发错误,从而不可能意外创建全局变量。

在普通JavaScript中,开发人员将不会收到将值分配给不可写属性的任何错误反馈。

在严格模式下,对不可写属性,仅getter属性,不存在属性,不存在变量或不存在对象的任何赋值都将引发错误。

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


37

"use strict"使JavaScript代码在严格模式下运行,这基本上意味着在使用前需要定义所有内容。使用严格模式的主要原因是为了避免意外地全局使用未定义的方法。

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

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

查看来自MDN的以下语句和示例:

“严格使用”指令
“严格使用”指令是JavaScript 1.8.5(ECMAScript版本5)中的新增功能。它不是语句,而是文字表达式,被早期JavaScript版本忽略。“使用严格”的目的是指示应在“严格模式”下执行代码。在严格模式下,例如,您不能使用未声明的变量。

使用“使用严格”的示例:
函数的严格模式:同样,要为函数调用严格模式,请输入确切的语句“使用严格”;(或“使用严格”;)在函数主体中的任何其他语句之前。

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

您可以在MDN上阅读更多内容


31

ECMAScript委员会中的一些人有一个很好的演讲:JavaScript的变化,第1部分:ECMAScript 5“,关于增量使用"use strict"开关如何使JavaScript实现者能够清理JavaScript的许多危险功能而不会突然破坏每个网站在世界上。

当然,它也讨论了其中的许多错误特征以及ECMAScript 5如何修复它们。


27

比较的小例子:

非严格模式:

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

严格模式:

'use strict';
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');
};

'a'.test();

// output
// false

String.prototype.test = function () {
  'use strict';
  
  console.log(typeof this === 'string');
};

'a'.test();

// output
// true


2
请注意,上面的代码会将i变量添加到全局范围(通常这不是最佳实践,严格模式有助于避免这种情况)。
迈克尔(Michael)

1
有人可以解释第二个例子吗?我不明白 this === 'a'在两个示例中都不应该吗?
MaximeW

19

请注意,它use strictEcmaScript 5中引入的,此后一直保留。

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

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

14

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

  1. 防止意外声明全局变量。"use strict()"使用var前请确保使用声明变量。例如:

    function useStrictDemo(){
     'use strict';
     //works fine
     var a = 'No Problem';
    
     //does not work fine and throws error
     k = "problem"
    
     //even this will throw error
     someObject = {'problem': 'lot of problem'};
    }
  2. 注意:该"use strict"指令只能在脚本或函数的开头识别。
  3. 该字符串"arguments"不能用作变量:

    "use strict";
    var arguments = 3.14;    // This will cause an error
  4. 将限制使用关键字作为变量。尝试使用它们将引发错误。

简而言之,这将使您的代码减少出错的可能性,进而使您编写好的代码。

要了解更多信息,可以在这里参考。


12

“使用严格”;ECMA致力于使JavaScript更加强大。它引入了JS使其至少有点“严格”的尝试(自90年代以来其他语言都实施了严格的规则)。实际上,它“迫使” JavaScript开发人员遵循某种编码最佳实践。不过,JavaScript非常脆弱。没有类型变量,类型方法等。我强烈建议JavaScript开发人员学习更强大的语言(例如Java或ActionScript3),并在JavaScript代码中实现相同的最佳做法,它将更好,更容易地工作。调试。


12

ECMAScript 5中引入了JavaScript“严格”模式。

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

"use strict";在您的JS文件的最顶部编写代码会启用严格的语法检查。它为我们执行以下任务:

  1. 如果您尝试分配给未声明的变量,则会显示错误

  2. 阻止您覆盖关键的JS系统库

  3. 禁止某些不安全或容易出错的语言功能

use strict也可以在各个功能中使用。始终将更好的做法包括use strict在您的代码中。

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



11

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

  • 防止意外的全局变量

  • 没有重复

  • 消除

  • 消除这种胁迫

  • 较安全的eval()

  • 不可变的错误

您也可以阅读本文以了解详细信息


11

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

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


7

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

  • “严格使用”指令是ECMAScript版本5中的新增功能。
  • 它不是语句,而是文字表达式,被早期JavaScript版本忽略。
  • “使用严格”的目的是指示应在“严格模式”下执行代码。
  • 在严格模式下,例如,您不能使用未声明的变量。

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

坏处

如果开发人员使用的是严格模式下的库,但是开发人员习惯于在正常模式下工作,则他们可能会对该库调用某些无法按预期方式执行的操作。

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

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

人们通常认为您不应该一开始就使用这些东西,但是一些开发人员不喜欢这种约束,而是想使用该语言的所有功能。


4

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

请检查以下以非严格模式编写的功能:

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.