什么是“严格模式”,它是如何使用的?
Posted
技术标签:
【中文标题】什么是“严格模式”,它是如何使用的?【英文标题】:What is "strict mode" and how is it used? 【发布时间】:2012-01-28 21:37:04 【问题描述】:我一直在查看 Mozilla Developer Network 上的 javascript 参考资料,发现了一个名为 "strict mode"
的东西。我读了一遍,我无法理解它的作用。有人可以简要解释一下它的用途和用途吗?
【问题讨论】:
相关:***.com/q/1335851/1461424 【参考方案1】:它的主要目的是做更多的检查。
只需在代码顶部添加"use strict";
,然后再添加其他任何内容。
例如,blah = 33;
是有效的 JavaScript。这意味着您创建了一个完全全局变量blah
。
但在严格模式下这是一个错误,因为您没有使用关键字“var”来声明变量。
大多数时候你并不是要在某个任意范围的中间创建全局变量,所以大多数时候blah = 33
是一个错误,程序员没有'实际上并不希望它成为一个全局变量,他们的意思是写var blah = 33
。
它同样不允许做很多技术上有效的事情。 NaN = "lol"
不会产生错误。它也不会改变 NaN 的值。使用严格的 this(和类似的奇怪语句)会产生错误。大多数人对此表示赞赏,因为没有理由写NaN = "lol"
,所以很可能是错字。
Read more at the MDN page on strict mode.
【讨论】:
这是 MDN 上文档的完全副本 那么您对它的实用性有什么不了解的呢?它旨在通过捕获有效但最有可能出现的错误来帮助开发。 “使用严格的 this”是什么意思?【参考方案2】:Simon 的回答中尚未提到的严格模式的一个方面是,在通过函数调用调用的函数中,严格模式将 this
设置为 undefined
。
这样的事情
function Obj()
this.a = 12;
this.b = "a";
this.privilegedMethod = function ()
this.a++;
privateMethod();
;
function privateMethod()
this.b = "foo";
在调用privateMethod
时会导致错误(因为您无法将属性添加到undefined
),而不是无用地将b
属性添加到全局对象。
【讨论】:
是的,需要添加privateMethod.bind(this)();
并拨打new
jsbin.com
严格模式下最重要的限制:docs.microsoft.com/en-us/scripting/javascript/advanced/…【参考方案3】:
添加了严格模式,以便有一个易于静态分析的 ECMAScript 子集,这将是该语言未来版本的一个很好的目标。严格模式的设计也是希望那些将自己限制在严格模式下的开发人员会犯更少的错误,并且他们所犯的错误会以更明显的方式表现出来。
Harmony,有望成为 ECMAScript 的下一个主要版本,将构建在 ES5 strict 之上。
Harmony 建立在 ES5 严格模式之上,以避免过多的模式。
其他一些语言实验也依赖于严格模式。 SES 依赖于 ES5 严格模式的可分析性。
SES(安全 ECMAScript)设计实验
通过删除或修复 ES5/Strict 中的功能来设计一种对象能力编程语言。
应该有从 SES 到 ES5/Strict 的直接翻译。
标准的Annex C解释了严格模式和普通模式的区别。
严格模式限制与例外
标识符“implements”、“interface”、“let”、“package”、“private”、“protected”、“public”、“static”和“yield”在严格模式代码中被归类为 FutureReservedWord 令牌. (7.6.12 [?])。 在处理严格模式代码时,符合规范的实现可能不会将 NumericLiteral (7.8.3) 的语法扩展为包含 B.1.1 中所述的 OctalIntegerLiteral。 在处理严格模式代码(参见 10.1.1)时,符合规范的实现可能不会将 EscapeSequence 的语法扩展为包括 B.1.2 中描述的 OctalEscapeSequence。 分配给未声明的标识符或其他不可解析的引用不会在全局对象中创建属性。当在严格模式代码中发生简单赋值时,其 LeftHandSide 不得评估为不可解析的引用。如果确实如此,则会引发 ReferenceError 异常 (8.7.2)。 LeftHandSide 也可能不是对具有属性值 [[Writable]]:false 的数据属性的引用,对具有属性值 [[Set]]:undefined 的访问器属性的引用,也可能不是对不存在的引用[[Extensible]] 内部属性值为 false 的对象的属性。在这些情况下,会引发 TypeError 异常 (11.13.1)。 标识符 eval 或参数可能不会显示为赋值运算符 (11.13) 或后缀表达式 (11.3) 的 LeftHandSideExpression,也不会显示为由前缀增量 (11.4.4) 或前缀减量 (11.4) 操作的 UnaryExpression。 5) 操作员。 严格模式函数的参数对象定义了名为“caller”和“callee”的不可配置访问器属性,它们在访问时抛出 TypeError 异常 (10.6)。 严格模式函数的参数对象不会与其函数的相应形式参数绑定动态共享其数组索引属性值。 (10.6)。 对于严格模式函数,如果创建参数对象,则本地标识符参数到参数对象的绑定是不可变的,因此可能不是赋值表达式的目标。 (10.5)。 如果严格模式代码包含具有多个任何数据属性 (11.1.5) 定义的 ObjectLiteral,则会出现 SyntaxError。 如果标识符“eval”或标识符“arguments”作为标识符出现在包含在严格代码中的 PropertyAssignment 的 PropertySetParameterList 中,或者如果其 FunctionBody 是严格代码 (11.1.5),则会出现 SyntaxError。 严格模式 eval 代码无法在调用者的变量环境中实例化变量或函数以进行 eval。相反,会创建一个新的变量环境,并将该环境用于 eval 代码 (10.4.2) 的声明绑定实例化。 如果在严格模式代码中计算 this,则 this 值不会强制转换为对象。 null 或 undefined 的 this 值不会转换为全局对象,原始值也不会转换为包装器对象。通过函数调用(包括使用 Function.prototype.apply 和 Function.prototype.call 进行的调用)传递的 this 值不会强制传递的 this 值到对象(10.4.3、11.1.1、15.3.4.3、15.3. 4.4)。 当删除运算符出现在严格模式代码中时,如果其 UnaryExpression 是对变量、函数参数或函数名的直接引用 (11.4.1),则会引发 SyntaxError。 当删除运算符出现在严格模式代码中时,如果要删除的属性具有属性 [[Configurable]]:false (11.4.1),则会引发 TypeError。 如果在严格代码中出现 VariableDeclaration 或 VariableDeclarationNoIn 且其标识符为 eval 或 arguments (12.2.1),则为 SyntaxError。 严格模式代码可能不包含 WithStatement。在这种情况下出现 WithStatement 是 SyntaxError (12.10)。 如果带有 Catch 的 TryStatement 出现在严格代码中并且 Catch 产生式的标识符是 eval 或 arguments (12.14.1),则会出现 SyntaxError 如果标识符 eval 或 arguments 出现在严格模式 FunctionDeclaration 或 FunctionExpression (13.1) 的 FormalParameterList 中,则会出现 SyntaxError 严格模式函数不能有两个或多个同名的形式参数。使用 FunctionDeclaration、FunctionExpression 或 Function 构造函数创建此类函数的尝试是 SyntaxError (13.1, 15.3.2)。 实现不能超出本规范中定义的范围,在名为调用者的属性或函数实例的参数的严格模式函数中的含义。 ECMAScript 代码不能在与严格模式函数(10.6、13.2、15.3.4.5.3)对应的函数对象上创建或修改具有这些名称的属性。 在严格模式代码中使用标识符 eval 或 arguments 作为 FunctionDeclaration 或 FunctionExpression 的标识符或作为形式参数名称 (13.1) 是 SyntaxError。尝试使用 Function 构造函数 (15.3.2) 动态定义此类严格模式函数将引发 SyntaxError 异常。
【讨论】:
【参考方案4】:ECMAScript 5 引入了严格模式的概念。
在代码中调用严格模式
严格模式适用于整个脚本或单个函数。它不适用于包含在 大括号中的块语句,尝试将其应用于此类上下文不会执行任何操作。
整个脚本:
假设我们正在创建 app.js,因此添加第一个语句使用脚本将对整个代码强制执行严格模式。
// app.js whole script in strict mode syntax
“use strict”;
// Now you can start writing your code
函数的严格模式:
要调用函数的严格模式,请输入确切的语句“use strict”;在任何其他语句之前的函数体的开头。
function yourFunc()
"use strict";
// Your function code logic
严格模式包含对正常 JavaScript 语义的一些更改。首先,严格模式通过将它们更改为抛出错误来消除一些 JavaScript 静默错误。
例如:使用严格模式的代码
在上面的代码示例中,没有在代码中使用严格模式,它不会抛出错误。因为我们正在访问变量 x
而没有声明它。所以在严格模式下访问未声明的变量会抛出错误。
现在让我们尝试访问一个变量 x,而不是在没有严格模式的情况下声明它。
(function()
x = 3;
)();
// Will not throw an error
使用严格模式的优势:
通过抛出错误来消除 JavaScript 静默错误。 修复了导致 JavaScript 引擎难以执行优化的错误。 使代码有时比非严格模式下的相同代码运行得更快 禁止某些可能在未来版本的 ECMAScript 中定义的语法。【讨论】:
【参考方案5】:严格模式对正常的 JavaScript 语义进行了几处更改。
严格模式通过将某些 JavaScript 静默错误更改为抛出错误来消除它们。
严格模式修复了导致 JavaScript 引擎难以执行优化的错误。
严格模式禁止某些可能在未来版本的 ECMAScript 中定义的语法。
【讨论】:
【参考方案6】:ECMAScript5
引入了一些新的对象和属性以及所谓的"strict mode"
。
严格模式是排除弃用功能的语言子集。严格的 模式是可选的并且不是必需的,这意味着如果您希望您的代码在 严格模式,你声明你的意图使用(每个函数一次,或者一次 整个程序)以下字符串:
"use strict";
【讨论】:
不只是一个子集吗?喜欢检查未定义的变量?【参考方案7】:2017年终于找到了文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
严格模式是一种选择加入受限制的 JavaScript 变体的方法。 严格模式不仅仅是一个子集:它故意有不同的 来自普通代码的语义。不支持严格模式的浏览器会 运行与浏览器不同的行为的严格模式代码,所以 不要依赖没有功能测试的严格模式来支持 严格模式的相关方面。严格模式代码和非严格模式 代码可以共存,因此脚本可以逐步选择进入严格模式。
严格模式对正常的 JavaScript 语义进行了几处更改。 首先,严格模式通过以下方式消除了一些 JavaScript 静默错误 更改它们以引发错误。其次,严格模式修复了以下错误 使 JavaScript 引擎难以执行优化: 有时可以使严格模式代码比完全相同的代码运行得更快 不是严格模式的代码。三、严格模式禁止某些语法 可能会在未来版本的 ECMAScript 中定义。
【讨论】:
【参考方案8】:严格模式是 ECMAScript 5 中的一项新功能,它允许开发人员将代码放入“严格”上下文中。 这种严格的上下文有助于开发人员通过抛出更多异常来避免错误。
如何在 js 中使用严格模式?
简单。把它扔到程序的顶部,为整个脚本启用它:
"use strict";
或者将它放在一个函数中,仅在该上下文中打开严格模式。
function imStrict()
"use strict";
// … your code (executes in strict mode) …
在 JS 中使用严格模式的优势
1。函数是块内的块范围 范围决定了代码区域中变量或其他资源的可见性或可访问性
案例一(无严格模式)
案例二(严格模式)
2。如果变量被赋值但未定义任何类型,则会引发错误/异常 在上面的例子中,“a”没有声明任何值(let, const, var)
3.如果在本地使用任何保留变量,则会引发错误 为将来的 JavaScript 版本保留的关键字不能用作严格模式下的变量名。
这些是: 民众 工具 界面 让 包裹 私人的 受保护 静止的 屈服 例如,
4.简单函数中的“this”在严格模式下指向“undefined”。 “this”关键字指的是调用函数的对象。 如果未指定对象,则严格模式下的函数将返回 undefined,而普通模式下的函数将返回全局对象(窗口) 以下是更好理解的示例
案例一(无严格模式)
案例二(严格模式)
5.不允许删除变量(或对象)和函数。
6.不允许重复参数名称
默认情况下,类的主体以严格模式执行。 例如:
class Rectangle
//code executed here are in Strict mode
参考文献
-
John Resig
MDN
W3School
【讨论】:
【参考方案9】:问题:
以下是我遇到的问题。我正在关注一个教程,它最终尝试编译以下 scss
文件并尝试从中生成 CSS 代码,
.fatty
width: percentage(6/7);
使用以下gulpfile.js
任务:
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('sass', function ()
return gulp.src('app/scss/styles.scss')
.pipe(sass())
.pipe(gulp.dest('app/css'))
);
所以我得到的错误如下:
~/htdocs/Learning/gulp1/node_modules/gulp-sass/index.js:66
let sassMap;
^^^
SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:373:25)
// stacktrace here...
解决方案:
所以它向我显示了我的 gulp-sass 模块中的 index.js
文件(基本上已锁定,不应编辑)。但是,如果我强行将"use_strict"
添加到该index.js
文件的顶部,它会顺利运行我的任务。
我很无奈,所以我一直用这个作为解决方案!但是在经历了其他一些 Stack Overflow Q&As, I saw the following answer 之后,如下所示:
sudo npm install -g n
sudo n stable
当我更新我的 Node.js(到版本 10.x),然后通过在终端运行以下命令来重建 Gulp 时,它指示我:
npm rebuild node-sass --force
一切都好。所以就这样解决了。我已经撤消了对index.js
Gulp.js 模块文件所做的更改。现在运行顺利。
【讨论】:
以上是关于什么是“严格模式”,它是如何使用的?的主要内容,如果未能解决你的问题,请参考以下文章
如何理解DocType? 什么是严格模式与混杂模式?如何触发这两种模式?
html的doctype作用?严格模式与混杂模式如何区分?它们有何意义