繁体   English   中英

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

What does "use strict" do in JavaScript, and what is the reasoning behind it?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

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

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

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

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

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

31 个回复

ES6 模块更新

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

原始答案

您可能会对这篇关于 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 5 的一个新特性。John Resig 写了 一个很好的总结

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

"use strict";

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

声明"use strict"; 指示浏览器使用 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等等。)(请参阅下面的examples部分以了解区别

  12. 不支持arguments.callee

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


例子:

  1. 严格模式代码不会为在其中创建的参数对象的属性设置别名
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" );

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

浏览器中的 ECMAScript 5“严格模式”支持。 这是什么意思?
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.
*/

提醒一句,你们这些强硬的程序员:对现有代码应用"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"的声明,我的目标是没有红色标记,但那是几年后的事了。

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

吵闹的失败

JavaScript 一直都有只读属性,但在 ES5 的Object.createProperty函数公开该功能之前,您无法自己创建它们。 如果您尝试将值分配给只读属性,它将静默失败。 赋值不会改变属性的值,但你的程序会继续进行,就好像它已经改变了一样。 这是一种完整性风险,可能导致程序进入不一致的状态。 在严格模式下,尝试更改只读属性将引发异常。

八进制

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

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

等等

arguments 伪数组在 ES5 中变得更像数组了。 在严格模式下,它会丢失其calleecaller属性。 这使得您可以在不放弃大量机密上下文的情况下将arguments传递给不受信任的代码。 此外,还消除了函数的arguments属性。

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


未来 JavaScript 版本的保留字

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

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语句。
  • 在严格模式下,所有变量都必须被声明:如果你为一个没有被声明为变量、函数、函数参数、catch-clause 参数或全局Object属性的标识符赋值,那么你将得到一个ReferenceError 在正常模式下,标识符被隐式声明为全局变量(作为全局Object的属性)
  • 在严格模式下,关键字this在作为函数(而不是方法)调用的函数中具有undefined值。 (在正常模式下this始终指向全局Object )。 这种差异可用于测试实现是否支持严格模式:
 var hasStrictMode = (function() { "use strict"; return this===undefined }());
  • 同样,当使用call()调用函数或以严格模式应用时, this正是call()apply 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

我的两分钱:

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

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

添加"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() { }

资料来源:

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

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

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

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

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

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

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

相信我。 与设计不佳的代码相比,开销可以忽略不计。 Doug Crockford 已经担任了几年的高级 JavaScript 开发人员,在这里有一篇非常有趣的帖子 就个人而言,我喜欢一直回到他的网站,以确保我不会忘记我的好习惯。

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

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

引用 w3schools

“使用严格”指令

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

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

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

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

为什么是严格模式?

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

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

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

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

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

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

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

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

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

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

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

使用“使用严格”的例子:
函数的严格模式:同样,要为函数调用严格模式,请输入确切的语句“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

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

ECMAScript 委员会的一些人发表了一篇精彩的演讲: JavaScript 的变化,第 1 部分:ECMAScript 5”关于"use strict"开关的增量使用如何允许 JavaScript 实现者清理 JavaScript 的许多危险特性,而无需突然破坏了世界上所有的网站。

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

比较的小例子:

非严格模式:

 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

请注意,在EcmaScript 5中引入了use strict并从那时起一直保留。

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

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

开发人员应该使用"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. 将限制关键字作为变量的使用。 尝试使用它们会引发错误。

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

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

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

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

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

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

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

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

  3. 禁止一些不安全或容易出错的语言特性

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

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

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

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

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

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

  • 防止意外的全局变量

  • 没有重复

  • 消除与

  • 消除这种强制

  • 更安全的 eval()

  • 不可变的错误

你也可以阅读这篇文章了解详情

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

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

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

坏处

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

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

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

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

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

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

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

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

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

它是否被视为最佳实践?

的,在使用 javascript 以包含Strict mode时,它​​被认为是最佳实践的一部分。 这是通过在您的 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

由于浏览器大战和管理不善,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"指令。 这是设计使然。

我应该在NodeJs 中使用严格模式吗?

默认的 NodeJS 设置,当您首先使用 npm init 命令初始化项目时,不使用严格模式。

NodeJS 默认使用CommonJS模块化。

如果您对此感到满意,则无需使用它。

您可能已经在考虑它可以在服务器端提供什么好处。


非严格模式示例:

假设我们有一个包含以下设置的 app.js 文件(我以这种方式导入模块以强调不同的模式)

//app.js
const nonStrictMode = require('./non-strict');
nonStrict.myFunc();

// non-strict.js
module.exports = {
    myFunc: () => {
        console.log('Non strict mode.');
        const fixed = {};
        Object.preventExtensions(fixed);
        fixed.newProperty = 'newProp';
        console.log(fixed.newProperty);
        console.log('Non strict mode finished.');
    }
};

它是非严格模式下完整有效的 JavaScript 语法。 但它不会像您期望的那样工作。 并且您不会收到编译时错误。

输出将是:

Non strict mode.
*undefined*
Non strict mode finished

那不是你想要实现的吗? 因此,如果抛出错误以通知您有关此“问题”的信息会更好。


严格模式示例:

// app.js
const strictMode = require('./strict');
strictMode.myFunc();

// strict.js
'use strict';

module.exports = {
    myFunc: () => {
        console.log('Strict mode on.');
        const fixed = {};
        Object.preventExtensions(fixed);
        fixed.newProperty = 'newProp';
        console.log('Strict mode finished.');
    }
};

输出将是:

Strict mode on.
TypeError: Cannot add property newProperty, object is not extensible.

那么,是不是不可能向冻结的对象添加属性?

不,事实并非如此,获得编译时错误比完全避免此错误要好得多。

如您所见,我使用了“严格使用”; 在这个 .js 文件的顶部。 所以也许你最好也使用这个配置。


或 .. 或,另一个例子:

// This will also become a global variable as global functions have
// global `this` as the contextual `this` in non strict mode
function hello() {
    foo = "Message";
}

当您为未声明的变量赋值时,JavaScript 会自动将其提升为默认模式下的全局变量。 在这里, 内存泄漏问题开始了。

为避免这种意外,请始终使用“use strict”以严格模式编写 JavaScript; JS 文件顶部的注释。 在严格模式下,上述将导致错误。


我希望我说清楚了。

也可以在 Nodejs 中使用它

通过将某些 JavaScript 静默错误更改为抛出错误来消除它们。 修复了使 JavaScript 引擎难以执行优化的错误:有时可以使严格模式代码比非严格模式的相同代码运行得更快。 禁止某些可能在 ECMAScript 的未来版本中定义的语法。

严格模式在 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+,这很重要。

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

还有更多功能,请在此处查看更多信息!

“使用严格”指令

它不是语句,而是文字表达式,被早期版本的 JavaScript 忽略。 “使用严格”的目的是表明代码应该以“严格模式”执行。 例如,在严格模式下,您不能使用未声明的变量。

//It's a new feature of ECMAScript 5. 
//With strict mode, you can not, for example, use undeclared variables.

Insert a 'use strict'; statement on top of your script:
/***START ANY JS FILE***/
'use strict';
var a = 2;
....
/***END***/ 
Or, insert a 'use strict'; statement on top of your function body:

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

例如:

class Person {
constructor() {
 a = 0;
 this.name = a;
 }
}

let p = new Person(); // ReferenceError: Can't find variable: a

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

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

搜索了一下,发现有些人加了"use strict"; 进入他们的 JavaScript 代码。 一旦我添加了语句,错误就不再出现。 不幸的是,谷歌没有透露这个字符串语句背后的大部分历史。 当然,它肯定与浏览器如何解释 JavaScript 有关系,但我不知道会产生什么效果。

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

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

1 ( ! + [] + [] + ![] ) [重复] 结果背后的原因是什么

这个问题在这里已经有了答案: 为什么 ++[[]][+[]]+[+[]] 返回字符串“10”? (10 个回答) 5 个月前关闭。 详细地说,这一行: 给出字符串"truefalse" 我一直在尝试它,但无法完全掌握发生的隐式转换,想知道结果背后的原因。 好奇而已。 ...

3 output背后的原因是什么?

输入: Output : 我期待什么? x = 20 y = 60 y = x = 20 x = y - 10 = 20 - 10 = 10 y = x + 10 = 20 预期 output : 为什么不是这样? 是因为首先评估表达式然后为变量赋值吗? ...

5 此输出背后的原因是什么?

这是代码。 此代码显示错误的输出。 我不知道为什么条件为真,为什么输出为假。 但是此代码显示正确的输出。 ...

2014-11-29 12:55:06 1 54   c
8 JavaScript中的var a =(expression1,expression2)背后的原因是什么?

通过查看一些JS代码,我发现了以下内容: 我以前从未发现过这样的东西,而且我不明白执行这样的事情的原因。 因此,我很好奇:是做这个事的人还是出于我的理解? 当我尝试检查类似(expression1, expression2) ,我发现它总是返回第二个表达式的值: 因此,如 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM