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

问题描述:

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

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

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

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

当前的浏览器是否对 “use strict”; 字符串做出响应,或者它是否供将来使用?

解决方案1:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

ES6 模块更新

在 native ECMAScript modules(带有 import 和 export 语句)和 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:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

这是 ECMAScript 5 的一个新特性。John Resig 写了 a nice summary。

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

"use strict";

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

解决方案3:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

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

功能列表(非详尽)

不允许全局变量。 (捕获缺少的 var 声明和变量名中的拼写错误)静默失败的分配将在严格模式下抛出错误(分配 NaN = 5;)尝试删除不可删除的属性将抛出(删除 Object.prototype)要求对象文字中的所有属性名称都是unique (var x = {x1: “1”, x1: “2”}) 函数参数名称必须是唯一的 (function sum (x, x) {…}) 禁止八进制语法 (var x = 023; some devs错误地假设前面的零不会改变数字。)在严格模式下禁止 with 关键字 eval 不引入新变量 禁止删除普通名称(删除 x;) 禁止以任何形式绑定或分配名称 eval 和参数 Strict mode 不使用形参对 arguments 对象的属性进行别名。 (例如,在函数 sum (a,b) { return arguments[0] + b;} 中之所以有效,是因为 arguments[0] 绑定到 a 等等。)(请参阅下面的示例部分以了解区别)arguments.callee 是不支持

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

例子:

严格模式代码不会为在其中创建的参数对象的属性设置别名

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" );

11.的例子不清楚,不清楚严格模式有什么区别。

解决方案4:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

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

huntsbot.com – 高效赚钱,自由工作

提醒一句,你们这些强硬的程序员:将 “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” 语句而不是红色标记,但那是几年后的事了。

解决方案6:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

使用“使用严格”;不会突然让你的代码变得更好。

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

'use strict';

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

考虑这个例子:

var a = 365;
var b = 030;

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

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

我应该在哪里使用“使用严格”;?

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

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

如何使用严格模式?

插入“使用严格”;脚本顶部的语句: // 文件:myscript.js ‘use strict’;变量 a = 2; … 请注意,文件 myscript.js 中的所有内容都将在严格模式下进行解释。或者,插入“使用严格”;函数体顶部的语句: function doSomething() { ‘use strict’; … } 函数 doSomething 的词法范围内的所有内容都将在严格模式下进行解释。词法作用域这个词在这里很重要。例如,如果您的严格代码调用不严格的库的函数,则只有您的代码在严格模式下执行,而不是被调用的函数。请参阅此答案以获得更好的解释。

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

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

作用域 从历史上看,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 中变得更像数组了。在严格模式下,它会丢失其被调用者和调用者属性。这使得您可以在不放弃大量机密上下文的情况下将参数传递给不受信任的代码。此外,还消除了函数的参数属性。在严格模式下,函数字面量中的重复键会产生语法错误。一个函数不能有两个同名的参数。函数不能具有与其参数之一同名的变量。函数不能删除自己的变量。现在尝试删除不可配置的属性会引发异常。原始值不是隐式包装的。

未来 JavaScript 版本的保留字

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

implements、interface、let、package、private、protected、public、static 和 yield

延伸阅读

严格模式 - JavaScript | MDN

浏览器支持严格模式

过渡到严格模式

解决方案7:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

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

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

例如,

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

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

解决方案8:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

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

您可以参考 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 语句。

在严格模式下,所有变量都必须被声明:如果你给一个没有被声明为变量、函数、函数参数、catch-clause 参数或全局对象属性的标识符赋值,那么你将得到一个 ReferenceError。在正常模式下,标识符被隐式声明为全局变量(作为全局对象的属性)

在严格模式下,关键字 this 在作为函数(而不是方法)调用的函数中具有 undefined 值。 (在正常模式下,它总是指向全局对象)。这种差异可用于测试实现是否支持严格模式:

var hasStrictMode = (function() { “use strict”; return this===undefined }());

同样,当使用 call() 或 apply 以严格模式调用函数时,这正是 call() 或 apply() 调用的第一个参数的值。 (在正常模式下,null 和 undefined 被全局 Object 替换,并且不是对象的值被转换为对象。)

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

在严格模式下,将代码传递给 eval() 时,您不能在调用者的范围内声明或定义变量或函数(就像在正常模式下一样)。相反,为 eval() 创建了一个新范围,并且变量和函数都在该范围内。该范围在 eval() 完成执行后被销毁。

在严格模式下,函数的 arguments-object 包含传递给该函数的值的静态副本。在正常模式下,arguments-object 具有某种“神奇”的行为:数组的元素和命名的函数参数都引用相同的值。

在严格模式下,当删除运算符后跟非限定标识符(变量、函数或函数参数)时,您将收到 SyntaxError。在正常模式下,删除表达式什么都不做,并被评估为假。

在严格模式下,当您尝试删除不可配置的属性时,您将收到 TypeError。 (在正常模式下,尝试简单地失败并且删除表达式被评估为假)。

在严格模式下,当您尝试为对象字面量定义多个具有相同名称的属性时,它会被视为语法错误。 (在正常模式下没有错误。)

在严格模式下,当函数声明具有多个同名参数时,它被认为是语法错误。 (在正常模式下没有错误。)

在严格模式下不允许使用八进制文字(这些是以 0x 开头的文字。(在正常模式下,某些实现确实允许使用八进制文字。)

在严格模式下,标识符 eval 和 arguments 被视为关键字。你不能改变它们的值,不能给它们赋值,你不能将它们用作变量、函数、函数参数或catch块的标识符的名称。

在严格模式下,对检查调用堆栈的可能性有更多限制。 arguments.caller 和 arguments.callee 在严格模式下的函数中导致 TypeError。此外,当您尝试读取它们时,严格模式下函数的某些调用者和参数属性会导致 TypeError。

“在严格模式下,不允许使用八进制文字(这些文字以 0x ... 开头)”八进制文字以前导 0 开头。

解决方案9:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

我的两分钱:

严格模式的目标之一是允许更快地调试问题。当某些错误的事情发生时,它会通过抛出异常来帮助开发人员,这可能会导致沉默和您网页的奇怪行为。我们使用 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 等工具缩小。它们也是 deprecated 并从未来的 JavaScript 版本中删除。

Sample

防止重复:

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

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

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

还有一些,但我需要获得更多的知识。

解决方案10:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

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

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

解决方案11:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

添加 “use strict”; 时,以下情况将在脚本执行前抛出 SyntaxError:

为未来的 ECMAScript 版本铺平道路,使用新保留的关键字之一(在 ECMAScript 6 之前):implements、interface、let、package、private、protected、public、static 和 yield。

在块中声明函数 if(a huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

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

原文链接:https://www.huntsbot.com/qa/A8Dr/what-does-use-strict-do-in-javascript-and-what-is-the-reasoning-behind-it?lang=zh_CN

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值