這些都能成為 Web 語法規(guī)范,強迫癥看不下去了
JavaScript 一直是飽受詬病,源于網(wǎng)景公司在 1995 年用了 10 天的時間創(chuàng)造。沒有什么能用 10 天創(chuàng)造就是完美的,可是某些特性一旦發(fā)布,錯誤或不完善的地方迅速成為必不可少的特色,并且是幾乎不可能改變。
Javascript 的發(fā)展非??欤緵]有時間調(diào)整設(shè)計。在推出一年半之后,國際標(biāo)準(zhǔn)就問世了。設(shè)計缺陷還沒有充分暴露就成了標(biāo)準(zhǔn)。
歷史遺留
比如常見的歷史設(shè)計缺陷:
- null 和 undefined 兩者非常容易混淆
- == 類型轉(zhuǎn)換的問題
- var 聲明創(chuàng)建全局變量
- 自動插入行尾分號
- 加號可以表示數(shù)字之和,也可以表示字符的連接
- NaN 奇怪的特性
- 更多...
Javascript 很多不嚴(yán)謹(jǐn)?shù)奶匦晕覀兛梢蕴砑?eslint 來規(guī)避。比如禁用 var 和 == 成了大多數(shù)人寫代碼的必備條件。
現(xiàn)在/未來
如今 CSS、DOM、HTML 規(guī)范由 W3C 來制定,JavaScript 規(guī)范由 TC39 制定。那些歷史缺陷也成為了過去,但是現(xiàn)在也出現(xiàn)了一些不盡人意的規(guī)范。
CSS 變量
聲明變量的時候,變量名前面要加兩根連詞線 --
- body {
- --foo: #7f583f;
- --bar: #f7efd2;
- }
var() 函數(shù)用于讀取變量。
- a {
- color: var(--foo);
- text-decoration-color: var(--bar, #7f583f);
- }
為什么選擇兩根連詞線(--)表示變量?因為 $ 被 Sass 用掉,@ 被 Less 用掉。_ 、-,用作為 IE 、chrome 兼容寫法。CSS 中已經(jīng)找不出來字符可以代替變量聲明了。為了不產(chǎn)生沖突,官方的 CSS 變量就改用兩根連詞線。
作為一個官方的標(biāo)準(zhǔn)規(guī)范,時刻影響后面的行業(yè)發(fā)展。竟然能被第三方的插件所左右,令人大跌眼鏡。有開發(fā)者吐槽:微軟的架構(gòu)師也是夠窩囊。
現(xiàn)在很多應(yīng)用都放棄了 Sass 和 less,轉(zhuǎn)向了 PostCSS 的懷抱。面向組件編程,根本用不到 Sass 和 less 里面的一些復(fù)雜功能。那么 -- 兩個字符的繁瑣將成為開發(fā)者永遠(yuǎn)的痛。
類私有屬性(proposal-class-fields)
JavaScript 中的 class 大家已經(jīng)不陌生了,簡直跟 Java 的 class 一模一樣。
基本用法:
- class BaseClass {
- msg = 'hello world';
- basePublicMethod() {
- returnthis.msg;
- }
- }
繼承:
- class SubClass extends BaseClass {
- subPublicMethod() {
- returnsuper.basePublicMethod();
- }
- }
靜態(tài)屬性:
- class ClassWithStaticField {
- static baseStaticMethod() {
- return'base static method output';
- }
- }
異步方法
- class ClassWithFancyMethods {
- *generatorMethod() {}
- async asyncMethod() {}
- async *asyncGeneratorMethod() {}
- }
而類私有屬性的提案目前已經(jīng)進(jìn)入標(biāo)準(zhǔn),它用了 # 關(guān)鍵字前綴來修飾一個類的屬性。
- class ClassWithPrivateField {
- #privateField;
- constructor() {
- this.#privateField = 42;
- }
- }
你沒看錯,不是 typescript 中的 private 關(guān)鍵字。
- class BaseClass {
- readonly msg = 'hello world';
- private basePrivateMethod() {
- return this.msg;
- }
- }
然而 # 的語法丑陋本身引起了社區(qū)的爭議:
- 「class fields 提案提供了一個極具爭議的私有字段訪問語法——并成功地做對了唯一一件事情,讓社區(qū)把全部的爭議焦點放在了這個語法上」。
- TS 投降主義已經(jīng)被迫實現(xiàn)了。
- No dynamic access, no destructuring is a deal breaker for me
- 我們制作一個 eslint 插件 no-private-class-fields 并使用下載計數(shù)來說明社區(qū)反對
- '#' 作為名稱的一部分會導(dǎo)致混淆,因為 this.#x !== this['#x'] 太奇怪了
前端架構(gòu)師、TC39 成員賀師俊也在知乎連發(fā)好幾篇文章吐槽 class fields
不妨大家看看關(guān)于 private 的 side:https://johnhax.net/2017/js-private/slide?qcon#0
提案地址:https://github.com/tc39/proposal-class-fields
globalThis
在不同的 JavaScript 環(huán)境中拿到全局對象是需要不同的語句的。在 Web 中,可以通過 window、self 取到全局對象,但是在 Web Workers 中只有 self 可以。在 Node.js 中,必須使用 global。非嚴(yán)格模式下,可以在函數(shù)中返回 this 來獲取全局對象,否則會返回 undefined
因此一個叫 global 的提案出現(xiàn)。主要用 global 變量統(tǒng)一上面的行為,但后面繞來繞去改成了 globalThis,引起了激烈討論。
globalThis 這個名字會讓 this 變得更加復(fù)雜。
- this 一直是困擾程序員的話題,尤其是 JavaScript 新手,關(guān)于它的博客文章源源不斷
- ES6 讓事情變得更簡單,因為可以告訴人們更喜歡箭頭函數(shù)并且只使用 this 內(nèi)部方法定義
- 在現(xiàn)代 JS(modules) 中,并沒有真正的全局 this,所以 globalThis 甚至不引用現(xiàn)有的概念
現(xiàn)在說這一切都是徒勞的,因為它已經(jīng)進(jìn)入 stage 4
提案地址:https://github.com/tc39/proposal-global
總結(jié)
JavaScript 中遺留的糟粕太多?,F(xiàn)在受到這些糟粕的影響,很多新的提案又不得不妥協(xié)。在未來,它會變得極其復(fù)雜。
也許某一天,會出現(xiàn)一個沒有歷史包袱的 JavaScript 子集來替換它。