likes
comments
collection
share

Vite爱好者,你必须知道“严格模式”这档事

作者站长头像
站长
· 阅读数 10

Hello World!大家好,我是大家的林语冰(挨踢版)~

粉丝质疑

之前肝了一期《Vue 为什么禁用 undefined》的水文,不幸的是,惨遭道友先质疑、再质疑。

Vite爱好者,你必须知道“严格模式”这档事

那这里我就简单讲两句:

  1. 任何编程语言中,某个单词能不能作为标识符,其实是由编译原理和语言规范共同决定的啦(安利哈工大的编译原理,反正我看得头大...)
  2. 严格模式和 undefined 没有直接关系喔,除非你硬要发生关系

事实证明,很多喵仙人知道严格模式,但没有完全知道,就像祂们对 undefined 一样处于似懂非懂的叠加态。

你知道吗?其实《ES6 标准入门教程》有一一列举严格模式的限制:

Vite爱好者,你必须知道“严格模式”这档事

如你所见,严格模式真的很机车欸,超多细节还蛮劝退的,背是不可能背的,这辈子都不可能背。(除非你有“超忆症”,就当我没说。)

大家连《ES6 标准入门教程》都不认真念吼,一整个被你打败了啦。

不过今天我们要伪科普的是其他东东,尤大劝学,严格模式不会不行。

今日头条(TLDR 省流版)

关于严格模式的若干错误解读,包括但不限于:

  1. 因为你没写 'use strict',所以你没开严格模式
  2. *精通 ES6 的严格模式是面试加分项
  3. *严格模式本质是做减法,所以严格模式是草率模式的子集
  4. 'use strict'; 必须出现在脚本/函数的首行

不幸的是,上述说法都有看不见的 BUG 魔鬼在细节,以上结论其实都是语冰以往被坑的“思想钢印”啦,今天就来一波以身试法反向教学,我超勇的啦。

彼芯到位,干货学会,懂得都懂,不懂 follow。葱葱葱~

尤大改变了世界线

你可能完全不 care 严格模式,反正你会说你从来没主动写过 'use strict' 这样子。

不好意思,你知道吗?尤雨溪先生已经把车门焊死了...

Vite 官网的 troubleshooting 章节是这样讲的,Vite 既无法处理、也不支持运行在草率模式的代码,因为 Vite 使用 ESM 模块,该模块始终使用严格模式。

Vite cannot handle and does not support code that only runs on non-strict mode (sloppy mode). This is because Vite uses ESM and it is always strict mode inside ESM.

简而言之,Vite 能且仅能支持严格模式喔。

所以如果你司的项目不幸使用了 Vite,哦豁,那你已经被严格模式包围了。

Vue 3.0 的版本名就叫做“One Piece”,汉化为“航海王”,而《航海王》正好有一句台词是这样讲的,时代的齿轮已经被我破坏,自此之后无人再有后路可走。

举一反一,前端工业时代的齿轮已经被尤大破坏,自此之后无人再有草率模式可用了啦。

大家可能还会想“曲线救国”,大不了就换 webpack 打包啊,不用 Vite 会怎样啦。我跟你说吼,你可以去瞄一眼 webpack 的打包结果,你猜祂有没有给你开启严格模式呢。

这就是严格模式最涩的地方,祂无处不在,不管你是否显式地使用 'use strict',你都可能不知不觉中开启了严格模式。

前端工程化中的优雅降级,很大程度依赖于 babel 生态,Vite/webpack/rollup/... 都集成了 babel 插件,比如可以将 ES6 的新语法优雅降级为 ES5 的旧语法。

就算你/你司特立独行吼,就不用 webpack/Vite 又怎样,你的代码有没有用到 babel 呢?如果有,恭喜你,你可能已经开启严格模式了啦,why?

Vite爱好者,你必须知道“严格模式”这档事

如你所见,import/export 是 ESM 模块语法,默认就是严格模式。

所以最危险的其实是你可能没有意识到你是在严格模式下写代码。如果你不懂严格模式就啪啪啪一顿操作,那你可能不知道你的代码在搞机掰。

严格模式的设计动机

所以说,严格模式必须要会啦。那严格模式为什么应运而生呢?

因为 ES5 之前存在很多 JS 垃圾语法不科学,但又不能暴力删除,毕竟这又不是猫猫绝育,不能说割蛋就割割蛋,所以就搞了个严格模式来渐进增强和优雅降级。

举个粒子,严格模式禁用 with 语句。

Vite爱好者,你必须知道“严格模式”这档事

如你所见,with 语句在严格模式会爆炸。

那这里想问一下大家吼,上面这段代码会被解析为以下哪段代码呢?

  • 1. key = value
  • 2. key = obj.value
  • 3. obj.key = value
  • 4. obj.key = obj.value

要我说,3 短 1 长选最长,啊不然咧!那反过来说,3 长 1 短选最短好像也没差啊...这个盲猜思路好像有点猪头欸。

答案是全都对也全都不对,具体的解析有 obj 的属性决定,任何一个平行宇宙有可能发生。

所以说 with 语句真的恶到爆,大家可能没用过呢。但其实 Vue 源码就有涉及,所以我们写不出 Vue 是有原因的。

严格模式不加分

我们要求大家都懂一点严格模式,听起来好像开始卷了。不幸的是,这甚至谈不上内卷,因为严格模式不是加分项,而是敲门砖。

你知道的,ES6 破蛋于 2015 年,2015 - 2017 那几年是 ES6 的主场优势,ES6 还算是你的简历加分项,之后 ES6 就是基本技能了。

反观严格模式,祂甚至比 ES6 还早出现,ES6 都快 10 岁了,而严格模式是 ES5 的特性,根本算不上加分项,所以内卷个机掰啦?如果你不懂严格模式,只能说你 ES6 入门了个寂寞。

所以,真心不建议在简历的加分项写熟悉严格模式,也不要在项目亮点中写精通 ES6。

严格模式不只是做减法

超多卷毛狒狒误会严格模式是草率模式的子集,祂们认为严格模式就是草率模式做减法,比如删除若干奇奇怪怪的语法特性就欧了,不知道你是不是这样子想的?

但其实严格模式其实不是草率模式的子集啦。

MDN 文档是这样子讲的,严格模式是草率模式的限制性变体(restricted variant)。

举个粒子,除了删除若干语法特性,严格模式还可能保留某个特性,只是针对该特性提供新的语义,覆盖其行为。

Vite爱好者,你必须知道“严格模式”这档事

如你所见,严格模式不会禁用 Function.prototype.apply() API,也不会废弃 this 关键字,但是会为 this 提供一龙一猪的运行时绑定:

  • 严格模式:this === null
  • 草率模式:this === globalThis

简而言之,严格模式不是通过简单粗暴地做减法就欧了,而是通过“断舍离”创造的,包括但不限于:

  • 当断则断的“断”:废弃/修复了若干影响 JS 引擎执行性能的语法
  • 舍近求远的“舍”:禁用若干未来 ES 规范相关的敏感语法
  • 离经叛道的“离”:将“静默失败”的运行时行为改为“抛出异常”

隐式/显式的严格模式

可执行代码开启严格模式的方式大致有两种喔:

  1. 显式手动使用 'use strict' 指令开启
  2. 隐式自动开启

为什么一个平平无奇的 'use strict' 字符串拥有如此神奇的魔力?

因为在不支持 ES5 严格模式的环境中,该指令只会被解释为一个人畜无害的字符串,不会有额外的副作用。而在支持严格模式的环境中,该指令就会自动触发严格模式,这种“双标黑魔法”的兼容性设计不就好棒棒啊!我只想说一个字,perfect!

举个粒子,开启严格模式的部分写法:

Vite爱好者,你必须知道“严格模式”这档事

除此之外,还有其他不常用的 eval/Function/... 等可执行代码也支持类似的方式。

另一个误区是,'use strict' 必须出现在首行才能生效,大部分情况下是这样子没错啦,但其实也不一定喔。

举个粒子,注释在第一行也不会影响啦。

Vite爱好者,你必须知道“严格模式”这档事

类型检查的“严格模式”

你知道的啦,TS 本就是 ES6 的超集,所以 TS 也支持严格模式。

其次,TS 的类型检查也可盐可甜,支持严格的类型检查,但不要和 ES6 的严格模式混淆了喔。

Vite爱好者,你必须知道“严格模式”这档事

ES6 的严格模式是针对语言的语义,TS 的类型严格检查是针对类型推断。

高能总结

草率模式是旧时代的残党,如果你不懂严格模式,新时代前端没有你的船。

  1. Vite 能且仅能支持严格模式
  2. 严格模式可以显式/隐式开启
  3. 严格模式 ES5 破蛋,不是 ES6 的新特性
  4. 严格模式是断舍离的限制性变体,不是草率模式的严格子集
  5. 'use strict'; 最好在脚本/函数的首行,但不是必须