正在加载...

严格模式

有几处错误以前会悄悄过去。严格模式把它们拦住。"use strict" 要写在最前面。此后,size = "regular" 既没有 let 也没有 const,就不会造出全局名字,而是抛出 ReferenceError。这一页上的那一行就是 ReferenceError。

待办和错误页是另外的结局

待办停在 done: buy tea。错误页故意抛了 new Error("missing size"),catch 读的是那句消息。这一页不抛你自己写的 Error。引擎抛出,是因为 size 从未声明。console.error 仍然不会抛。

指令只有一个位置有效

"use strict" 只有作为脚本的第一条语句,或者作为某一个函数里的第一条语句,才会生效。后面再出现的字符串什么都不会改变。可以只有一个函数是严格的,脚本其余部分不是。模块本来就是严格的,所以那里的指令是多余的。

setSize 在做什么

setSize 给 size 赋值,却没有声明它。调用放在 try 里。不会出现全局的 size。

未声明的赋值

javascript
"use strict";
function setSize() {
size = "regular";
}
try {
setSize();
} catch (error) {
console.log(error.name);
}

日志是 ReferenceError。修法是 let size = "regular"。若 drink 是 tea,并且 size 已经这样声明,label 可以返回 tea / regular。写成 order.size 是另一种说得通的改法,因为那个名字确实存在。

用名字调用,和在对象上调用

按函数自己的名字调用,不会设置 this。严格模式里 this 是 undefined。在 order 上调用方法,会把 this 设成那个对象,于是 this.drink 是 tea。

bare 调用里的 this

javascript
"use strict";
function bare() {
return this;
}
const order = {
drink: "tea",
label() {
return this.drink;
}
};
console.log(bare());
console.log(order.label());

两次日志先是 undefined,然后是 tea。不要在 bare 里面读 this.drink。那里没有对象,这样读会抛出。

四处不同

左边是从前那种静默行为。右边是这条指令做成的结果。

📊 这条指令改了什么

旧的静默行为 使用 "use strict"
未声明就写 size = "regular" 会创建全局名字 ReferenceError
bare 里的 this 是全局对象 undefined
重复参数时后一个生效 SyntaxError
对已声明变量使用 delete 会返回 false SyntaxError

重复的参数,或者 delete size,在脚本被读取时就失败,那是 SyntaxError,try 抓不到。赋值带来的 ReferenceError 发生在函数运行时,所以 catch 看得到。只要属性可以删掉,delete order.drink 在两种模式里都仍然允许。

这个页面

页面是一段严格脚本。赋值失败,错误的名字被写到页面上。

页面上的 ReferenceError

html
<!DOCTYPE html>
<html>
<body>
<p id="line">…</p>
<script>
"use strict";
const line = document.querySelector("#line");
try {
size = "regular";
} catch (error) {
line.textContent = error.name;
}
</script>
</body>
</html>

这一行读作 ReferenceError。不是 done: buy tea。也不是 caught / missing size。在 size 前面加上 let,这个 catch 就不再运行。

五个短练习

  1. 在 "use strict" 下运行 setSize。日志是 ReferenceError。
  2. 把赋值改成 let size = "regular"。抛出消失。
  3. 调用 bare()。值是 undefined。
  4. 调用 order.label()。值是 tea。
  5. 读页面。这一行是 ReferenceError。

真会踩到的地方

  • 把指令放在另一条语句后面
  • 以为未声明的赋值会造出全局名字
  • 在 bare 调用里读 this.drink
  • 用 try 去接重复参数
  • 把这一行读成 done: buy tea
  • 把这一行读成 caught / missing size

记住这些

  • 指令放在最前
  • 未声明的 size = "regular" 抛出 ReferenceError
  • bare 里的 this 是 undefined,order.label() 返回 tea
  • 重复参数和对变量使用 delete 都是 SyntaxError
  • 页面上的那一行是 ReferenceError

🧠 测试您的知识

准备开始

测试您的知识

通过这个互动测验挑战自己,看看你对这个主题的理解程度如何

❓
6
问题
🎯
70%
及格要求
♾️
∞
时间
🔄
∞
尝试次数

📝 说明

  • 仔细阅读每个问题
  • 为每个问题选择最佳答案
  • 您可以随时重新参加测验
  • 您的进度将显示在顶部