JavaScript中使用“严格使用”是什么,它背后的原因是什么?



12 Answers

这是ECMAScript 5的一个新功能。John Resig写了一个很好的总结

它只是一个你放入JavaScript文件的字符串(无论是在你的文件的顶部还是在函数的内部),看起来像这样:

"use strict";

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

Question

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

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

做一些搜索,我意识到有些人加上"use strict"; 到他们的JavaScript代码中。 一旦我添加了该语句,错误就会停止显示。 不幸的是,Google没有透露这个字符串声明背后的大部分历史。 当然,它必须与JavaScript如何被浏览器解释有关,但我不知道会产生什么效果。

那么什么是"use strict"; 所有关于,它意味着什么,它仍然是相关的?

目前的浏览器是否对"use strict";做出回应"use strict"; 字符串还是将来使用?




The main reasons why developers should use "use strict" are:

  1. Prevents accidental declaration of global variables.Using "use strict()" will make sure that variables are declared with var before use. 例如:

    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. NB: The "use strict" directive is only recognized at the beginning of a script or a function.
  3. The string "arguments" cannot be used as a variable:

    "use strict";
    var arguments = 3.14;    // This will cause an error
    
  4. Will restrict uses of keywords as variables. Trying to use them will throw errors.

In short will make your code less error prone and in turn will make you write good code.

To read more about it you can refer http://www.w3schools.com/js/js_strict.asp .




Just wanted to add some more points.

The Reason to Use Strict Mode--->

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

  • Strict mode changes previously accepted "bad syntax" into real
    错误。

  • As an example, in normal JavaScript, mistyping a variable name
    creates a new global variable.

  • 在严格模式下,这会引发错误,从而无法意外创建全局变量。

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

在严格模式下抛出错误的东西不允许使用变量而不声明它:

"use strict";
 x = 3.14;                // This will cause an error

对象也是变量。

不允许使用对象而不声明它:

  "use strict";
  x = {p1:10, p2:20};      // This will cause an error

不允许删除变量(或对象)。

  "use strict";
   var x = 3.14;
   delete x;                // This will cause an error

出于安全考虑,eval()不允许在调用它的作用域中创建变量:

"use strict";
 eval ("var x = 2");
 alert (x);               // This will cause an error

在像f()这样的函数调用中,这个值是全局对象。 在严格模式下,它现在是未定义的。

“严格使用”仅在脚本开始时才被识别。




When adding "use strict"; , the following cases will throw a SyntaxError before the script is executing:

  • Paving the way for future ECMAScript versions , using one of the newly reserved keywords (in prevision for ECMAScript 6 ): implements , interface , let , package , private , protected , public , static , and yield .

  • Declaring function in blocks

    if(a<b){ function f(){} }
    
  • Octal syntax

    var n = 023;
    
  • this point to the global object.

     function f() {
          "use strict";
          this.a = 1;
     };
     f(); 
    
  • Declaring twice the same name for a property name in an object literal

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

    This is no longer the case in ECMAScript 6 ( bug 1041128 ).

  • Declaring two function arguments with the same name function

    f(a, b, b){}
    
  • Setting a value to an undeclared variable

    function f(x){
       "use strict";
       var a = 12;
       b = a + x*35; // error!
    }
    f();
    
  • Using delete on a variable name delete myVariable;

  • Using eval or arguments as variable or function argument name

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

资料来源:




Note that use strict was introduced in EcmaScript 5 and was kept since then.

Below are the conditions to trigger strict mode in ES6 and ES7 :

  • Global code is strict mode code if it begins with a Directive Prologue that contains a Use Strict Directive (see 14.1.1).
  • Module code is always strict mode code.
  • All parts of a ClassDeclaration or a ClassExpression are strict mode code.
  • Eval code is strict mode code if it begins with a Directive Prologue that contains a Use Strict Directive or if the call to eval is a direct eval (see 12.3.4.1) that is contained in strict mode code.
  • Function code is strict mode code if the associated FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, MethodDefinition, or ArrowFunction is contained in strict mode code or if the code that produces the value of the function's [[ECMAScriptCode]] internal slot begins with a Directive Prologue that contains a Use Strict Directive.
  • Function code that is supplied as the arguments to the built-in Function and Generator constructors is strict mode code if the last argument is a String that when processed is a FunctionBody that begins with a Directive Prologue that contains a Use Strict Directive.



Normally java script does not follow strict rules hence increasing chances of errors. After using "use strict" , the java script code should follow strict set of rules as like in other programming languages such as use of terminators, declaration before initialization etc.

If "use strict" is used then the code should be written by following a strict set of rules hence decreasing the chances of errors and ambiguities.




如果人们担心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.
*/



使用'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将被意外地绑定到全局对象,所以不是初始化一个新对象,而是默默地篡改全局变量。 在这些情况下,严格模式会将其绑定到undefined ,这将导致构造函数抛出异常,从而更快地检测到错误。

嘈杂的失败

JavaScript一直具有只读属性,但是直到ES5的Object.createProperty函数公开该功能之前,您才能创建它们。 如果您试图将值分配给只读属性,则它将以无提示方式失败。 作业不会改变该属性的值,但程序会像进行一样继续。 这是一种可能导致程序进入不一致状态的完整性危害。 在严格模式下,尝试更改只读属性会引发异常。

八进制

在字长为3的倍数的机器上进行机器级编程时,八进制(或基数为8)的数字表示非常有用。使用字长为60位的CDC 6600主机时,需要八进制数。 如果你能读八进制数,你可以看一个字作为20位数字。 两个数字表示操作码,一个数字表示8个寄存器之一。 在从机器代码到高级语言的缓慢过渡期间,认为在编程语言中提供八进制形式是有用的。

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

等等

参数伪数组在ES5中变得更像数组。 在严格模式下,它会丢失其calleecaller属性。 这使得将您的arguments传递给不可信的代码成为可能,而不会放弃很多保密上下文。 此外,函数的arguments属性被消除。

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

未来JavaScript版本的保留字

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

implementsinterfaceletpackageprivateprotectedpublicstaticyield

进一步阅读




“严格使用”; 是程序员不会使用JavaScript的松散或不良属性的保险。 这是一个指导,就像统治者会帮助你制定直线一样。 “严格使用”将有助于您进行“直接编码”。

那些宁愿不使用统治者直线行的人通常会在那些要求他人调试他们的代码的页面中结束。

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

现代JavaScript实践应该始终唤起“严格使用”; 附注。 ECMA Group选择“严格”模式的唯一原因是允许经验较少的编码人员访问JavaScript,然后给予适应新的和更安全编码实践的时间。




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

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

"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 -statement。
  • 在严格模式下,所有变量都必须声明:如果您为尚未声明为全局Object变量,函数,函数参数,catch-clause参数或属性的标识符赋值,则会得到一个ReferenceError 。 在正常模式下,标识符被隐式声明为全局变量(作为全局Object的属性)
  • 在严格模式下,这个关键字的值在未被调用为函数的函数中(而不是方法) undefined 。 (在正常模式下, this总是指向全局Object )。 这种差异可用于测试实现是否支持严格模式:
var hasStrictMode = (function() { "use strict"; return this===undefined }());
  • 另外,当通过call()调用函数或在严格模式下apply函数时,则this正是call()apply()调用的第一个参数的值。 (在正常模式下, nullundefined被全局Object替代,而不是对象的值被转换为对象。)

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

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



“严格使用”; is the ECMA effort to make JavaScript a little bit more robust. It brings in JS an attempt to make it at least a little "strict" (other languages implement strict rules since the 90s). It actually "forces" JavaScript developers to follow some sort of coding best practices. Still, JavaScript is very fragile. There is no such thing as typed variables, typed methods, etc. I strongly recommend JavaScript developers to learn a more robust language such as Java or ActionScript3, and implement the same best practices in your JavaScript code, it will work better and be easier to debug.




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

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




There's a good talk by some people who were on the ECMAScript committee: Changes to JavaScript, Part 1: ECMAScript 5" about how incremental use of the "use strict" switch allows JavaScript implementers to clean up a lot of the dangerous features of JavaScript without suddenly breaking every website in the world.

Of course it also talks about just what a lot of those misfeatures are (were) and how ECMAScript 5 fixes them.




Related