热搜:前端 nest neovim nvim

undefined 为什么不是字面量?

lxf2023-06-05 02:59:04

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

今天我们来伪科普一道前端面试题——undefined 为什么不是字面量?


考点大纲

我们会讨论以下若干面试考点,包括但不限于—— undefined 为什么不是字面量? 懂得都懂,不懂关注,日后再说~


I. undefined 恒等于 undefined 原始值吗?

我们在《undefined 是隐式全局变量吗?》中曾经说过,globalThis.undefined 是“不被定义的属性”——

  • 不可赋值
  • 不可枚举
  • 不可配置

undefined 为什么不是字面量? 换而言之,globalThis.undefined 是鲁棒只读的全局属性。

虽然但是,当我们需要使用 undefined 原始值的时候,我们会理所当然地使用剪短的 undefined,而不是一寸长一寸强的 globalThis.undefined

这是因为大多数人没有意识到这是一个看不见的 BUG,祂们拥有和语冰一样的“思想钢印”——undefined 是“字面量”。

虽然但是,“从来如此,便对么?”

事实上,undefined 是字面量只是一个都市传说,undefinedundefined 原始值是两码事。

不幸的是,我们从来没有质疑过——undefined 恒等于 undefined 原始值吗?

举个粒子,当我们把 undefined 妖魔化,祂就异化为“魔术字面量”。 undefined 为什么不是字面量? 猫眼可见,undefined 并不恒等于 undefined 原始值,undefined 是“真-un-defined”,我们 defined 啥,undefined 就是啥。倘若你愿意,undefined 可以被赋值为任意值。

那一天,人类终于回想起了,在 undefined 支配之下的错觉,还有那被囚禁于偏见中的那份无知。

根据反证法,我们也不难推理出 undefined 不是字面量,有部分书籍说 “undefined 是字面量”其实也是一种“思想钢印”。

MDN Web Docs 曾经说过,字面量代表 JS 中的值。这些值是你在脚本中直接提供的固定值,而非变量。

Literals represent values in JavaScript. These are fixed values—not variables—that you literally provide in your script.

举个粒子,当我们写下一个字面量时,祂的值就是固定的。 undefined 为什么不是字面量? 猫眼可见,字面恒久远,一个永流传。字面量就是字面上直接表示的固定值,一眼万年,此生不换。

数字 9 就是数字 9,祂不会基因突变成 666;字符串 'cat' 就是字符串 'cat',祂不会基因突变成“薛定谔/盯裆猫”。

还有一个小众的冷知识,字面量不是合法的标识符,即字面量不允许作为变量名等。字面量一般只能作为右值——即赋值操作符右边的值,undefined 既可以是右值,也可以是左值。

不幸的是,undefined 既不恒等于 undefined 原始值,一言不合说变就变,而且又可以作为变量名,字面量不喜欢的样子祂都有。

反证法可得,undefined 妥妥地不是字面量。

语冰有幸百度过一本书叫做《你的孩子不是你的孩子》,举一反一,你的 undefined(属性)也不是你的 undefined(原始值)。

综上所述,undefined 不是字面量,因为祂并不恒等于 undefined 原始值,又是一个合法的标识符。


II. 当我们谈论 undefined 时我们在谈论什么?

地球人都知道,我们的集体潜意识里有一个根深蒂固的“思想钢印”——undefined 是字面量,上一节我们已经辟谣成功,那其实只是一个见怪不怪的“前端曼德拉效应”。

百度百科曾经说过,“曼德拉效应”是一个心理学效应,指大众对历史的集体记忆与史实不符。 undefined 为什么不是字面量? 这在前端人中还蛮常见的,譬如说语冰叫大家给我彼芯,大家常常集体选择性失忆。

举个粒子,以下是若干“曼德拉效应”现象,包括但不限于:

  • 米老鼠的穿搭是背带裤
  • 《爱我中华》的歌词是“五十六个民族,五十六枝花”
  • 其他三连可观看内容......

举一反一,“前端曼德拉效应”指的是——前端人对于某些冷知识的解读出现了从众的认知偏差,集体潜意识植入根深蒂固的“思想钢印”,错得不能说是一龙一猪,只能说是一猫一样。

语冰有幸百度过一本书《冬牧场》@李娟中就有类似的描写,大家都愿意盲从,好像世上最安全的事就是让自己消失在“多数”之中。

undefined 为什么不是字面量?

举个粒子,前端集体潜意识里若干见怪不怪的都市传说/“思想钢印”:

  • 万物皆对象(才怪)
  • undefined 是字面量(才怪)
  • 原始类型存储在栈上,对象类型存储在堆里(才怪)
  • “盯裆猫”的尾巴是白色的
  • 其他三连可观看内容......

免责声明

“前端曼德拉效应”是语冰凭空捏造的一个梗,大家理性吃瓜就好,面试千万别用,“试试就逝世”,用一下就会失业,被 pass 了后果自负。

问题在于,抛开事实不谈,undefined 给人锚定的第一印象就特别像字面量。为什么我们会对 undefined 有一种油然而生的字面量既视感?

语冰的主观臆测是,因为我们不是 JS 引擎......我知道这是废话,我也知道你很急,但是你先别急,且听我理直气壮地胡说八道,一本正经地胡言乱语。

我的意思是,之所以我们戴上 undefined 是字面量的“有色眼镜”,是因为我们有眼睛,而 JS 引擎没有......

更确切地说,我们和 JS 引擎看待代码的方式不能说是一猫一样,只能说是一龙一猪。

人类是一种极其依赖视觉的动物,我们看到帅哥美女就会流口水,我们看到大猫就会拔腿就跑——跑得比追女孩还快,我们看到 VSCode “阳了”就会头皮发麻,我们看到彼芯就会一键三连...... undefined 为什么不是字面量?

举一反一,我们看到 undefined 长得跟 null 等字面量一猫一样——都是英文,都是小写,就会下意识地类比推理,undefined 大概率是字面量。

注意,这绝对不是因为我们太笨,恰恰相反,这种类比和建模能力能帮我们人族有效地整理信息、固化记忆,关键还节能。

大家可能不知道,你的脑子质量占比约 2%,能量消耗却高达约 20%,这就是我们高中学习特别容易挨饿的原因,你现在可能也饿了,因为语冰的人类高质量视频太烧脑了。

这种视觉驱动的能力确实能保证我们卷毛狒狒在进化中适者生存,虽然但是,却不能保证我们在前端已死的生态中绝处逢生。

大家可能不知道,现在科学已经证伪了“眼见为实”,现实并非如你所见。

举个粒子,棋盘阴影错觉。 undefined 为什么不是字面量? 猫眼可见,棋盘阴影中的区域和阴影外的区域其实是同色,但是人眼无法准确识别。

举一反一,undefined 看起来像字面量,不代表 undefined 就是字面量,就像龙猫非猫,龙猫原型其实是毛丝鼠。

undefined 为什么不是字面量?

事实上,大小写并不是定义字面量的客观条件,就好像我们倾向于把 NaN 当做字面量,但我们不会把 Promise 当做字面量。这主要是我们依赖视觉使用了错误的心智模型。

那么当我们在谈论 undefined 时,我们其实在谈论什么?

对于 JS 开发者而言,我们或许只是想要一个 undefined 原始值。

虽然但是,undefined 在 JS 中起码有三层含义,包括但不限于:

  • undefined 原始值
  • Undefined 原始类型
  • undefined 属性

一旦我们没有主动区分“三位一体”的 undefined,就很容易把三者混淆。可能你只是想要一个 undefined 原始值,但你的代码是 undefined,这默认其实是一个 undefined 属性,只是祂的缺省值刚好是 undefined 原始值,但不完全是。

问题在于,你有没有对自己写下的代码有正确的认知?你真的知道你写的代码是什么意思吗?如果你不知道,你就不可能写下语义化的代码,也不可能理解下面的代码。

举个粒子,undefined 的“三生三世”:

  • void 0undefined 原始值)
  • typeof/===(Undefined 类型的人脸识别)
  • globalThis.undefined(全局属性)

undefined 为什么不是字面量? 猫眼可见,Vue 等开源项目就使用 void 0 等最佳实践来编写可维护的、可读性高的代码。

综上所述,undefined 的语义并不相通,我只觉得祂们双标。

总而言之,源码是灵活的,你怎么使用 undefined 都没关系,语冰想强调的是,我们必须自主严格区分 undefined 的“一语三关”,我们必须明确知道自己想要的是哪一种 undefined,而我们的源码必须尽量体现对应的语义。


III. undefined 的本质是什么?

我们利用反证法证明了 undefined 不是字面量,我们也重新建模了“三位一体”的 undefined

虽然但是,还有一个问题,当我们在代码中写下 undefined 这个单词时,undefined 表达的是什么?

换而言之,倘若我们和 JS 引擎换位思考,那么站在 JS 引擎的角度,undefined 的本质是什么鬼物?

你知道的,面试的时候我们可能会说,ES 语言规范曾经说过, undefined 是 Undefined 原始类型有且仅有的唯一值——undefined 原始值。

The Undefined type has exactly one value, called undefined.

面试官或许会接受,但倘若我们的面试官是 JS 引擎,那么这个答案 0 分。

我们或许会说,undefined 默认是全局属性 globalThis.undefined,祂的缺省值是 undefined 原始值。

这个答案既符合面试八股文,又符合 JS 引擎的基本解读,60 分。

上面的答案在面试中都问题不大,最大的问题是——没有亮点。那么有没有更加凡尔赛、直击本质的答案呢?我们总以为面试的最高境界是吊打面试官,其实这种面试思维是年轻人太气盛,原因在于吊打面试官是小概率事件,别忘了姜还是老的辣,更大概率是我们是被面试官反杀的普信男,小丑还是我自己。

面试的本质其实不是吊打面试官,而是提高你的分辨率和曝光率。 undefined 为什么不是字面量?

换而言之,你要做的是吊打其他面试者,甚至不需要吊打。你要做的其实是让面试官对你有印象,只要你能给面试官植入“思想钢印”,那么就放大了你的存在感,弱化了祂者的市场竞争力。所以我们应该做的是在细节上凡尔赛,从而潜移默化地给面试官留下深刻印象。

当然,面试时暴走掀桌子也算“深刻印象”,但一般不建议使用,因为凡尔赛的威力在于“凡”的同时还能把你“赛”进面试官的记忆宫殿里。

那么对于 JS 引擎,undefined 到底是什么鬼物呢?

答案是 undefined 的本质是一个“标识符”。

这个答案 9 个面试者估计 9 个都不会这么回答,却又直击本质,因为我们是从 JS 引擎的角度来解读 undefined,所以足够凡尔赛,无形装逼,最为给力。

问题在于,首先你得知道什么是标识符,否则不就是在面试时给自己挖坑吗?

MDN 文档曾经说过,标识符是代码中用来标识变量、函数或属性的字符序列。

An identifier is a sequence of characters in the code that identifies a variable, function, or property.

顾名思义,标识符其实就是用来标识某些数据的符号,比如变量名可以标识一个变量的值。

举个粒子,变量名、属性名、函数名等都是合法标识符(名)。

举个反粒子,字面量、保留字等都是非法标识符。

如你所见,“标识符”这个概念其实在我们的代码里见怪不怪,但是很少有人面试会或者敢这样说,因为这个术语一般用在编译原理领域。面试时为了更好地 sell yourself(贩卖自我),我们不妨凡尔赛地使用“标识符”这个术语,以彰显我们的编程素养和专业品质。

那么如何证明语冰不是在虾扯蛋,undefined 确实标识符呢?

注意,不能因为语冰说是,undefined 就是标识符,语冰并没有言出法随的超能力。不然语冰叫大家彼芯,大家早就疯狂打 call 了。我们可以“大胆假射”,但要“小心球证”。

首先我们可以科学推理,上文我们提及标识符可以是变量名/属性名等,那么 undefined 作为 globalThis.undefined 属性,自然可以推理出 undefined 是属性名,也就是标识符。

再者说,既然标识符是编译原理相关的术语,那我们不烦使用一些编译器相关的工具人来验证。 undefined 为什么不是字面量? 猫眼可见,undefined 被解析为标识符。

扪心自问,假如 9 个面试者只有一个这么凡尔赛,那么作为面试官你会 pick 谁呢?下次想吊打面试官的时候,记得三思而后行,你真的想吊打面试官吗?

语冰作为彻头彻尾的挨踢节能主义者,我更倾向于难度系数更低的选择——对除了面试官之外的其他面试者降维打击。

综上所述,语冰的个人心证是,undefined 的本质是一个长得像字面量的标识符——写做 undefined,读做 undefined 标识符。

免责声明

本文示例代码默认均为 ESM(ECMAScript Module)筑基测评,因为现代化前端开发相对推荐集成 ESM,其他开发环境下的示例会额外注释说明,edge cases 的解释权归大家所有。

今天的《ES6 混合理论》就讲到这里啦,我们将在本合集中深度学习若干奇奇怪怪的前端面试题/冷知识,感兴趣的前端爱好者可以关注订阅,也欢迎大家自由言论和留言许愿,共享 BUG,共同内卷。

吾乃前端的虔信徒,传播 BUG 的福音。

我是大家的林语冰,我们一期一会,不散不见,掰掰~

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!