JavaScript中的"use strict":它能避免错误吗?全面解析

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

什么是JavaScript中的"use strict",为什么它备受争议?

\n\n

你是否曾经写过运行起来“有点奇怪”的JavaScript代码?变量自己就声明了,this指向了全局对象而不是你期望的对象,错误被默默地吞掉了?欢迎来到“脏”JS的世界。

\n\n

"use strict"指令既不是函数也不是运算符。它实际上是你脚本或函数的模式切换开关。当你在文件或函数的开头写上"use strict"时,你就是在告诉JavaScript引擎:“嘿,不要原谅我的错误。要更严格,但也要更诚实。”

\n\n

这个话题是Stack Overflow上最热门的问题之一(有数千次浏览)。让我们来弄清楚严格模式到底做了什么,为什么它被发明出来,以及如何用它来避免搬起石头砸自己的脚。

\n\n

如何启用严格模式?

\n\n

只有两种方法:

\n\n
    \n
  • 全局(针对整个脚本): 在文件的第一行写上"use strict";。
  • \n
  • 局部(针对函数): 在函数体的第一行写上"use strict";。
  • \n
\n\n
// 全局严格模式\n"use strict";\nlet x = 10;\n\n// 局部严格模式\nfunction myFunc() {\n  "use strict";\n  let y = 20;\n}
\n\n

重要提示: 如果你在同一个文件中混合使用严格和非严格代码(例如,拼接脚本),可能会出现问题。最好对单个函数或模块使用严格模式(ES6模块自动处于严格模式)。

\n\n

"use strict"防止的5大错误

\n\n

"use strict"的主要目标是将JavaScript的“静默”错误转化为显式异常(可以被捕获并抛出的错误)。以下是5个最常见的场景。

\n\n

1. 禁止隐式创建全局变量

\n\n

这是经典案例。在普通模式下,如果你忘记写var、let或const,变量会自动变成全局变量。这可能导致难以发现的bug。

\n\n
// 没有"use strict"\nfunction sum(a, b) {\n  total = a + b; // 错误?不。total变成了全局变量!\n}\nsum(2, 3);\nconsole.log(total); // 5 — 可以运行,但这很糟糕。\n\n// 使用"use strict"\n"use strict";\nfunction sumStrict(a, b) {\n  total = a + b; // ReferenceError: total is not defined\n}\nsumStrict(2, 3); // 错误!代码会立即崩溃。
\n\n

如何避免? 始终声明变量。使用let和const代替var,以避免变量提升和意外的全局变量。

\n\n

2. 给不可写的属性赋值

\n\n

在普通模式下,JavaScript会默默地忽略修改NaN、undefined或冻结对象的尝试。在严格模式下,会抛出错误。

\n\n
"use strict";\n\n// 尝试重写NaN\nNaN = 123; // TypeError: Cannot assign to read only property 'NaN'\n\n// 尝试修改冻结对象\nconst obj = Object.freeze({name: "Alice"});\nobj.name = "Bob"; // TypeError: Cannot assign to read only property 'name'
\n\n

如何避免? 不要尝试重写内置常量。有意识地使用Object.freeze()。

\n\n

3. 删除变量、函数和参数

\n\n

你不能删除通过var或let声明的变量,也不能删除函数。在普通模式下,这会被忽略。

\n\n
"use strict";\n\nvar x = 10;\ndelete x; // SyntaxError: Delete of an unqualified identifier in strict mode.\n\nfunction foo() {}\ndelete foo; // SyntaxError
\n\n

如何避免? 不要对变量使用delete。它只用于删除对象的属性:delete obj.prop。

\n\n

4. 函数参数重复

博客

书籍推荐