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

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

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

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

那么什么是"use strict";所有的一切,这意味着什么,并且仍然有意义?

当前的浏览器是否响应"use strict";字符串还是将来使用?

答案

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

引用一些有趣的部分:

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

和:

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

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

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

// Non-strict code...

(function(){
  "use strict";

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

// Non-strict code...

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

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

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

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

这是 ECMAScript 5 的新功能。JohnResig 对此进行了很好的总结

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

"use strict";

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

声明"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 开发人员网络 ]

如果人们担心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"可能很危险!这东西不是一些让人感觉愉悦,表情愉悦的标签,您可以在代码上拍打它,使其变得 “更好”。使用"use strict"杂语,浏览器会突然在从未发生过的随机位置抛出异常,这仅仅是因为您正在执行默认 / 宽松 JavaScript 允许但严格 JavaScript 讨厌的事情!您可能会遇到严格的违规情况,这些隐匿在您的代码中很少使用的调用中,这些调用只会在最终运行时才抛出异常 - 例如,在付费客户使用的生产环境中!

如果您要尝试一下,最好将"use strict"与全面的单元测试以及严格配置的 JSHint 构建任务一起应用,这将使您充满信心,您的模块不会出现死角可怕的是,因为您已启用严格模式。或者,嘿,这是另一种选择:就是不要在您的任何旧代码中添加"use strict" ,说实话,这样做可能更安全。 绝对不要在您不拥有或维护的任何模块(例如第三方模块)上添加"use strict"

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

当我采用"use strict"时,我的项目不是一个新项目。结果,我的 IDE 充满了红色标记,因为我对模块的一半没有"use strict" ,而 JSHint 对此表示抱怨。这让我想起了将来应该做的重构。我的目标是消除我所有的"use strict"声明,以免出现红标,但这距离现在已经有几年了。

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

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

'use strict';

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

考虑以下示例:

var a = 365;
var b = 030;

implementsinterfaceletpackageprivateprotectedpublicstaticyield


进一步阅读

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

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

例如,

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

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

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

您可以参考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变量,函数,函数参数,子句参数或属性的标识符,那么您将获得ReferenceError 。在正常模式下,标识符隐式声明为全局变量(作为 global Object的属性)
  • 在严格模式下,关键字this的值在作为函数(而不是方法)调用的函数中具有undefined的值。 (在正常模式下, this始终指向全局Object )。此差异可用于测试实现是否支持严格模式:
var hasStrictMode = (function() { "use strict"; return this===undefined }());
  • 同样,当使用call()调用函数或以严格模式apply函数时, this恰好是call()apply()调用的第一个参数的值。 (在正常模式下,将nullundefined替换为全局Object ,并将不是对象的值强制转换为对象。)

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

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

我的两分钱:

严格模式的目标之一是允许更快地调试问题。当某些错误的事情发生时,它会引发网页异常的异常行为,从而引发异常,从而有助于开发人员。当我们使用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

样品

with语句消除:

使用uglify-js 之类的工具无法使with语句最小化 。它们也已弃用,并从将来的 JavaScript 版本中删除。

样品

防止重复:

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

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

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

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

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

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