undefined 的“七大罪”(自律版)

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

今天我们来伪科普一下下——uzi 为什么是神?undefined 为什么是坑?)


敏感话题(省流版)

如果说设计模式是最佳实践,那么反模式就是“最渣实践”。

为了避免成为“渣男”,我们有必要了解一些编程的反模式。这些反模式可能会带来挨踢负债(Technical debt,技术负债),将来需要重构代码来还债。

前端冷知识

反模式(Anti-patterns/pitfalls),是指用来解决问题的带有共同性的不良方法。它们已经经过研究并分类,以防止日后重蹈覆辙,并能在研发尚未投产时辨认出来。

undefined 为粒子的反模式包括但不限于——

  1. 禁止重写全局属性,因为不同模式行为不一
  2. 禁止声明 undefined 变量,因为同名局部变量会屏蔽全局属性
  3. 禁止无脑使用 undefined 初始化,因为编程动机不够明确
  4. 尽量不要“光明正大”地使用 undefined,因为“隐性性状”更加鲁棒
  5. 禁止动态修改变量的类型,因为静态编程更好维护
  6. 禁止魔术字面量,因为硬编码有悖 DRY 原则
  7. 禁止使用 ==undefined 指纹识别,因为 null == undefined

懂得都懂,不懂关注,日后再说~


首先是犯下贪婪之罪的“四不像”

地球人都知道,ES5 之前 undefined 可重写,ES5 之后鲁棒只读的 undefined 赋能祂先天免疫一些阴间操作。

举个粒子,当我们尝试重写全局属性时,试试就逝世。

code.png

猫眼可见,undefined 的内心毫无波动。

虽然但是,相同代码在运行时的不同模式下测评可能出现不同的“四不像”行为:

  • 严格模式禁止赋值,运行时直接“阳了”,抛出异常
  • 非严格模式赋值无效,运行时静默失败

换而言之,非严格模式下即使赋值无效也不会报错,undefined 表面好像被重写了,但其实并没有,其他读码人可能理解出现歧义。

百度百科曾经说过,所谓“四不像”指的是——往往一个设计模型可以暴露不同的接口给用户,不同的接口表现了模型的不同方面。

举一反一,原则上我们禁止重写全局属性,不作死就不会死,规避不同模式运行时的双标行为。


其次是犯下嫉妒之罪的“竞争危害”

地球人都知道,ES3 之前没有 undefined 全局属性,所以会遗留一些颇具时代局限性的最佳实践。

举个粒子,分享一些历史遗留的 undefined 标识符。

history.png

猫眼可见,undefined 不是保留字,原则上允许祂作为合法的标识符,即使不合理。

举个粒子,当我们尝试重复声明同名变量时,全局属性就会被屏蔽(shadow,遮蔽)。

scope-1st.png

猫眼可见,局部同名变量会屏蔽全局属性,作用域链机制的“竞争危害”会导致默认的 undefined 变量失真。

百度百科曾经说过,所谓“竞争危害”指的是——缺乏预见事件以不同顺序发生的后果。

举一反一,原则上我们禁止重复声明屏蔽全局属性,不要嫉妒全局变量,避免指猫为狗催生 undefined 的“竞争危害”。


然后是犯下暴怒之罪的“万应灵”

地球人都知道,undefined 是 JS(JavaScript)最抽象的元值(metavalue),原则上允许祂作为兼容对象/原始类型的合法初始值。

举个粒子,遇事不决 undefined因为太麻烦就全点防御力了(因为太麻烦就全写 undefined 了)。

static-init.png

猫眼可见,一言不合 undefined,但是编程意图并不明确。

变量的命名应该顾名思义,尽量体现值的含义,反之亦然,初始值应该符合变量名的“人设”,避免指猫为狗。

语冰再重新整理自己的偏见后,形成的全新偏见是——当且仅当变量的类型和值同时不明确时,我们才勉为其难地安排 undefined 作为无状态的占位符。

举个粒子,当我们对变量一无所知时,我们才使用 undefined

stateless.png

猫眼可见,当且仅当变量的类型未知/类型需要兼容时,我们才按需赋值 undefined

百度百科曾经说过,所谓“万应灵”指的是——一个对象了解的东西太多,或者要做太多的事情,就好像无所不能一样。

举一反一,原则上我们禁止一言不合 undefined,因为 undefined 的无能在于祂无所不能。


再然后是犯下暴食之罪的“屠龙术”

地球人都知道,undefined 不是字面量,这意味着 undefined 变量并不恒等于 undefined 原始值。

举个粒子,当我们使用 undefined 赋值时,不要画蛇添足。

implicit.png

猫眼可见,我们推荐直接使用 undefined 的隐性性状,避免“光明正大”地使用 undefined

百度百科曾经说过,所谓“屠龙术”指的是——没有必要的复杂设计。

举一反一,原则上我们禁止冗余的初始赋值,大可不必把饭叫饥,矫枉过正。


接着是犯下色欲的“乱麻球”

地球人都知道,JS 是一门动态类型语言,原则上允许变量的类型和值动态决定。

虽然但是,动态类型并非无类型——当变量的值确定时,祂的类型也确定了。

举个粒子,我们尝试用静态编程来使用动态语言。

static-assign.png

猫眼可见,值变型不变,赋值看条件。变量具体的初始值尚未尘埃落定,我们可以优先赋值为具体类型的“特殊值”,提前明示读码人变量的类型约束。

百度百科曾经说过,所谓“乱麻球”指的是——系统没有可辨认的结构,就像一团乱麻一样。

举一反一,原则上我们禁止偷懒直接使用 undefined 重置变量,优先静态初始化和赋值,保持类型不变,避免变量偷猫盗狗,代码变成一团乱麻。


还有是犯下懒惰之罪的“硬编码”

大家大抵都通读过阮一峰的《ECMAScript6 标准入门教程》,其中提及的“魔术字符串”就是“魔术字面量”的一种。

《ECMAScript6 标准入门教程》曾经说过,“魔术字符串”指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。

举个粒子,使用魔术字符串/数字的代码可维护性/可读性十分赶人。

magic.png

猫眼可见,魔术字面量存在明显的短板,包括但不限于——

  1. 重复硬编码可能拼写错误,IDE 不会提示,也没有代码补全
  2. 代码耦合度高,一处出错,处处排错纠错,违背 DRY 原则
  3. 编程意图不够直观,你码我猜,谁都不爱

举个粒子,模块化共享常量解耦重构,消除魔术字面量。

de-magic.png

猫眼可见,优雅得不谈。

举一反一,undefined 也有类似的魔术副作用,我们也可以通过模块化的共享常量来重构。

isundefi.png

猫眼可见,我们封装了鲁棒的 undefined 共享常量,按需使用即可。

百度百科曾经说过,所谓“硬编码”AKA“写死”,指的是在实现某系统用途上设死该系统的运作环境。

举一反一,原则上我们不推荐偷懒反复地使用魔术字面量,也不推荐直接使用 undefined 全局属性,我们可以重构解耦,规避硬编码的挨踢负债。


最后是犯下傲慢之罪的“反抽象”

MDN 文档曾经说过,undefined 是一个见怪不怪的标识符,碰巧成为全局属性。

换而言之,undefined 没有设计为像 null 一样的字面量,某种意义上成为了现代化前端开发的历史包袱。

你知道的,我们可以通过 globalThis.undefined 来替换 undefined,但吹毛求疵的话,频繁访问全局作用域会降低性能,也不是一种好习惯,因为涉及全局作用域的操作总是让我们在意作用域污染的隐患。

抛开 undefined 自己的历史包袱不谈,undefined 的指纹识别也魔鬼在细节。

举个粒子,因为 Undefined 类型有且仅有一个原始值—— undefined,所以我们既可以通过类型,也可以通过值来识别 undefined

typeof.png

猫眼可见,我们可以通过类型判断/值比较来识别 undefined 原始值。

虽然但是,使用“三长”才能避免“两短”——=== 严格相等优于 == 宽松相等,我们要扬长避短。

BTW,虽然对象不存在的属性缺省值(default,默认值)是 undefined,但是这不能用来判断对象的属性所有权。

举个粒子,对象属性值为 undefined 并不意味着对象没有该属性。

own.png

猫眼可见,禁止盲人摸猫,undefined 并不是判断对象属性所有权的充分必要条件。

百度百科曾经说过,所谓“反抽象”指的是需要的功能并不暴露给用户,导致用户要在较高层次重新实现一些功能。

举一反一,原则上允许我们通过类型/值比较对 undefined 进行指纹识别,但是禁止 ==,使用 === 扬长避短。BTW,原则上不推荐使用 undefined 判断对象属性的所有权。


免责声明

地球人都知道,坏的制度会让好人作恶,好的制度能让坏人从良。

举一反一,坏的代码会让黑客破防,好的代码能让码农内卷。

相信我,你永远可以相信 undefined,只要你不使用祂。

换而言之,任何时候、任何情况下,我们承诺不首先使用核武器undefined)。

CatCAT 曾经说过,关于 undefined 有“撸码十诫”——

第一诫——除了我之外,你不可有别的值。

第二诫——不可为自己冗余赋值。

第三诫——不可妄称 undefined 的名。

第四诫——不可遇事不决 undefined

第五诫——当知书达礼,仅仅知道本文的知识是不行的,还要懂得给语冰彼芯送礼。

第六诫——不可变型,值变型不变,赋值看条件。

第七诫——不可 ==

第八诫——不可万物皆可 undefined

第九诫——不可魔术字面量。

第十诫——不可判断对象属性。

你知道的,代码千万条,优雅第一条,撸码不鲁棒,同事两行泪。

今天我们伪科普一下下 undefined 的反模式和安利了语冰的若干代码洁癖(个人向),即使不是最佳实践,也希望对你有所帮助。

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

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYEDnecb' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片