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

Posted

技术标签:

【中文标题】“use strict”在 JavaScript 中做了啥,背后的原因是啥?【英文标题】:What does "use strict" do in JavaScript, and what is the reasoning behind it?“use strict”在 JavaScript 中做了什么,背后的原因是什么? 【发布时间】:2018-02-01 14:46:29 【问题描述】:

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

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

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

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

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

【问题讨论】:

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

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。

【讨论】:

【参考方案2】:

这是 ECMAScript 5 的新功能。John Resig 写了a nice summary 。

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

"use strict";

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

【讨论】:

【参考方案3】:

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

功能列表(非详尽)

    不允许全局变量。 (发现变量名中缺少var 声明和拼写错误)

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

    尝试删除不可删除的属性会抛出 (delete Object.prototype)

    要求对象字面量中的所有属性名称都是唯一的 (var x = x1: "1", x1: "2")

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

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

    禁止with 关键字

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

    禁止删除普通名称 (delete x;)

    禁止以任何形式绑定或分配名称 evalarguments

    严格模式不会使用形式参数为arguments 对象的属性起别名。 (例如在function sum (a,b) return arguments[0] + b; 中,这是因为arguments[0] 绑定到a 等等。)

    不支持arguments.callee

[参考:Strict mode,Mozilla 开发者网络]

【讨论】:

11.的例子不清楚,不清楚严格模式有什么区别。【参考方案4】:

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

【讨论】:

【参考方案5】:

请注意,你们这些勤奋的程序员们:将"use strict" 应用于现有代码可能是危险的!这东西不是你可以在代码上贴上“更好”的感觉良好、快乐的表情贴纸。使用"use strict" pragma,浏览器会突然在它以前从未抛出过的随机位置抛出异常,因为在那个地方你正在做一些默认/松散的 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" 声明而不是红色标记,但那是几年后的事了。

【讨论】:

【参考方案6】:

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

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

'use strict';

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

考虑这个例子:

var a = 365;
var b = 030;

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

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


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

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

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


如何使用严格模式?

    在脚本顶部插入 'use strict'; 语句:

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

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

    或者,在函数体顶部插入 'use strict'; 语句:

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

    函数doSomething词法范围 中的所有内容都将在严格模式下进行解释。 词法作用域这个词在这里很重要。例如,如果您的 strict 代码调用了一个 not strict 库的函数,那么只有您的代码在严格模式下执行,而不是被调用的函数。请参阅this answer 以获得更好的解释。


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

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

范围

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

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

严格代码的好处之一是像YUI Compressor 这样的工具 处理时可以做得更好。

隐含的全局变量

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

全球泄漏

有多种情况可能导致this 绑定到全局对象。例如,如果您忘记 在调用构造函数时提供new 前缀, 构造函数的this 将意外绑定到全局对象,所以 而不是初始化一个新对象,而是静默 篡改全局变量。在这些情况下,严格模式将 而是将this 绑定到undefined,这将导致构造函数 而是抛出异常,从而可以检测到很多错误 早点。

嘈杂的故障

JavaScript 一直都有只读属性,但你 在 ES5 的 Object.createProperty 之前无法自己创建它们 功能暴露了这种能力。如果您尝试分配一个值 到只读属性,它会默默地失败。该任务将 不更改属性的值,但您的程序将继续进行 虽然它有。这是一种完整性危害,可能导致程序 进入不一致的状态。在严格模式下,尝试更改 只读属性会抛出异常。

八进制

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

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

等等

arguments 伪数组变多了一点 ES5 中的类数组。在严格模式下,它会丢失其calleecaller 特性。这样就可以将您的 arguments 传递给不受信任的 在不放弃大量机密上下文的情况下编写代码。此外,该 arguments 函数的属性被消除了。

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


为将来的 JavaScript 版本保留的字词

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

implementsinterfaceletpackageprivateprotectedpublicstaticyield


进一步阅读

Strict Mode - JavaScript | MDN Browser support for strict mode Transitioning to strict mode

【讨论】:

【参考方案7】:

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

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

例如,

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

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

【讨论】:

【参考方案8】:

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

您可以参考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-statement。 在严格模式下,所有变量都必须被声明:如果你为一个没有被声明为变量、函数、函数参数、catch-clause 参数或全局Object 属性的标识符赋值,那么你将获取ReferenceError。在正常模式下,标识符被隐式声明为全局变量(作为全局 Object 的属性) 在严格模式下,关键字this 在作为函数(而不是方法)调用的函数中具有值undefined。 (在正常模式下this 始终指向全局Object)。这个差异可以用来测试一个实现是否支持严格模式:
var hasStrictMode = (function()  "use strict"; return this===undefined ());
1234563 (在正常模式下,nullundefined 被全局 Object 替换,并且不是对象的值被转换为对象。)

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

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

【讨论】:

"在严格模式下不允许使用八进制文字(这些是以 0x ... 开头的文字)" 八进制文字以 0 开头。【参考方案9】:

我的两分钱:

严格模式的目标之一是允许更快地调试问题。当发生某些可能导致网页无声和奇怪行为的错误事件时,它会通过抛出异常来帮助开发人员。在我们使用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 时,代码会抛出错误。

Uncaught ReferenceError: nameoftree is not defined

Sample

消除with 声明:

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

Sample

防止重复:

当我们有重复的属性时,它会抛出一个异常

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

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

还有一些,但我需要获得更多关于这方面的知识。

【讨论】:

【参考方案10】:

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

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

【讨论】:

【参考方案11】:

添加"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 (bug 1041128) 不再是这种情况。

用同名函数声明两个函数参数

f(a, b, b)

为未声明的变量设置值

function f(x)
   "use strict";
   var a = 12;
   b = a + x*35; // error!

f();

在变量名delete myVariable;上使用delete

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

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

来源:

Transitioning to strict mode 在 MDN 上

Strict mode 在 MDN 上

JavaScript’s Strict Mode and Why You Should Use It 在 Colin J. Ihrig 的博客上(存档版)

【讨论】:

ECMAScript 2015 再次允许重复的属性名称!见MDN documentation。【参考方案12】:

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

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

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

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

更多信息请访问Strict Mode- Javascript

【讨论】:

【参考方案13】:

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

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

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

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

【讨论】:

【参考方案14】:

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

【讨论】:

【参考方案15】:

Quoting from w3schools:

“使用严格”指令

“use strict”指令是 JavaScript 1.8.5 中的新指令(ECMAScript 版本 5)。

它不是一个语句,而是一个文字表达式,之前被忽略了 JavaScript 版本。

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

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

为什么是严格模式?

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

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

例如,在普通 JavaScript 中,错误输入变量名会导致 一个新的全局变量。在严格模式下,这会抛出一个错误, 避免意外创建全局变量。

在普通的 JavaScript 中,开发者不会收到任何错误反馈 为不可写的属性赋值。

在严格模式下,对不可写属性的任何赋值, getter-only 属性,不存在的属性,不存在的 变量或不存在的对象会抛出错误。

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

【讨论】:

【参考方案16】:

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

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

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

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

“use strict”指令“use strict”指令是新的 JavaScript 1.8.5(ECMAScript 版本 5)。这不是一个声明,而是一个 文字表达式,被早期版本的 JavaScript 忽略。这 “使用严格”的目的是表明代码应该是 以“严格模式”执行。使用严格模式,您不能,例如, 使用未声明的变量。

使用“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。

【讨论】:

【参考方案17】:

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

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

【讨论】:

【参考方案18】:

比较的小例子:

非严格模式:

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

【讨论】:

【参考方案19】:

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

以下是ES6和ES7中触发严格模式的条件:

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

【讨论】:

【参考方案20】:

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

    防止意外声明全局变量。使用"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';
    
    
    注意:"use strict" 指令仅在脚本或函数的开头被识别。

    字符串"arguments"不能用作变量:

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

    将限制将关键字用作变量。尝试使用它们会引发错误。

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

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

【讨论】:

【参考方案21】:

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

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

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

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

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

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

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

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

【讨论】:

【参考方案22】:

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

【讨论】:

【参考方案23】:

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

【讨论】:

【参考方案24】:

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

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

【讨论】:

【参考方案25】:

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

防止意外的全局变量

没有重复

消除

消除这种强制

更安全的 eval()

不可变对象的错误

你也可以阅读article了解详情

【讨论】:

【参考方案26】:

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

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

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

缺点

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

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

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

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

基本示例和参考请通过:

https://www.tutorialsteacher.com/javascript/javascript-strict

【讨论】:

【参考方案27】:

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

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

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

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

【讨论】:

【参考方案28】:

严格模式消除了在非严格模式下会被忽略的错误,从而使 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'],
        ,
    ;
    

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

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

删除变量、函数或参数在严格模式下是禁忌。

"use strict";
 function x(p1, p2) ; 
 delete x; // This will cause an error

复制参数名称在严格模式下不允许

 "use strict";
 function x(p1, p1) ;   // This will cause an error

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

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

【讨论】:

【参考方案29】:

由于浏览器大战和管理不善,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 解析为未定义,这是我们所期望的。

"use strict"

function run() 
  console.log(this);


run(); // undefined

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

【讨论】:

以上是关于“use strict”在 JavaScript 中做了啥,背后的原因是啥?的主要内容,如果未能解决你的问题,请参考以下文章

“use strict”如何修改Javascript中“this”的规则?

(11) 严格模式(use strict)

Javascript 严格模式use strict详解

Javascript 严格模式use strict详解

"use strict"详解

为什么使用 use strict