这些都能成为 Web 语法规范,强迫症看不下去了

13,671 阅读5分钟

JavaScript 一直是饱受诟病,源于网景公司在 1995 年用了 10 天的时间创造。没有什么能用 10 天创造就是完美的,可是某些特性一旦发布,错误或不完善的地方迅速成为必不可少的特色,并且是几乎不可能改变。

Javascript 的发展非常快,根本没有时间调整设计。在推出一年半之后,国际标准就问世了。设计缺陷还没有充分暴露就成了标准。

历史遗留

比如常见的历史设计缺陷:

  • nullundefined 两者非常容易混淆
  • == 类型转换的问题
  • var 声明创建全局变量
  • 自动插入行尾分号
  • 加号可以表示数字之和,也可以表示字符的连接
  • NaN 奇怪的特性
  • 更多...

Javascript 很多不严谨的特性我们可以添加 eslint 来规避。比如禁用 var== 成了大多数人写代码的必备条件。

现在/未来

如今 CSS、DOM、HTML 规范由 W3C 来制定,JavaScript 规范由 TC39 制定。那些历史缺陷也成为了过去,但是现在也出现了一些不尽人意的规范。

CSS 变量

声明变量的时候,变量名前面要加两根连词线 --

body {
  --foo: #7f583f;
  --bar: #f7efd2;
}

var() 函数用于读取变量。

a {
  color: var(--foo);
  text-decoration-color: var(--bar, #7f583f);
}

为什么选择两根连词线(--)表示变量?因为 $Sass 用掉,@Less 用掉。_-,用作为 IEchrome 兼容写法。CSS 中已经找不出来字符可以代替变量声明了。为了不产生冲突,官方的 CSS 变量就改用两根连词线。

作为一个官方的标准规范,时刻影响后面的行业发展。竟然能被第三方的插件所左右,令人大跌眼镜。有开发者吐槽:微软的架构师也是够窝囊。

现在很多应用都放弃了 Sassless,转向了 PostCSS 的怀抱。面向组件编程,根本用不到 Sassless 里面的一些复杂功能。那么 -- 两个字符的繁琐将成为开发者永远的痛。

类私有属性(proposal-class-fields)

JavaScript 中的 class 大家已经不陌生了,简直跟 Javaclass 一模一样。

基本用法:

class BaseClass {
  msg = 'hello world';

  basePublicMethod() {
    return this.msg;
  }
}

继承:

class SubClass extends BaseClass {
  subPublicMethod() {
    return super.basePublicMethod();
  }
}

静态属性:

class ClassWithStaticField {
  static baseStaticMethod() {
    return 'base static method output';
  }
}

异步方法

class ClassWithFancyMethods {
  *generatorMethod() {}
  async asyncMethod() {}
  async *asyncGeneratorMethod() {}
}

而类私有属性的提案目前已经进入标准,它用了 # 关键字前缀来修饰一个类的属性。

class ClassWithPrivateField {
  #privateField;

  constructor() {
    this.#privateField = 42;
  }
}

你没看错,不是 typescript 中的 private 关键字。

class BaseClass {
  readonly msg = 'hello world';

  private basePrivateMethod() {
    return this.msg;
  }
}

然而 # 的语法丑陋本身引起了社区的争议:

「class fields 提案提供了一个极具争议的私有字段访问语法——并成功地做对了唯一一件事情,让社区把全部的争议焦点放在了这个语法上」。

TS 投降主义已经被迫实现了。

No dynamic access, no destructuring is a deal breaker for me

我们制作一个 eslint 插件 no-private-class-fields 并使用下载计数来说明社区反对

'#' 作为名称的一部分会导致混淆,因为 this.#x !== this['#x'] 太奇怪了

前端架构师、TC39 成员贺师俊也在知乎连发好几篇文章吐槽 class fields

不妨大家看看关于 private 的 side: johnhax.net/2017/js-pri…

提案地址:github.com/tc39/propos…

globalThis

在不同的 JavaScript 环境中拿到全局对象是需要不同的语句的。在 Web 中,可以通过 windowself 取到全局对象,但是在 Web Workers 中只有 self 可以。在 Node.js 中,必须使用 global。非严格模式下,可以在函数中返回 this 来获取全局对象,否则会返回 undefined

因此一个叫 global 的提案出现。主要用 global 变量统一上面的行为,但后面绕来绕去改成了 globalThis,引起了激烈讨论。

globalThis 这个名字会让 this 变得更加复杂。

  1. this 一直是困扰程序员的话题,尤其是 JavaScript 新手,关于它的博客文章源源不断
  2. ES6 让事情变得更简单,因为可以告诉人们更喜欢箭头函数并且只使用 this 内部方法定义
  3. 在现代 JS(modules) 中,并没有真正的全局 this,所以 globalThis 甚至不引用现有的概念

现在说这一切都是徒劳的,因为它已经进入 stage 4

提案地址:github.com/tc39/propos…

总结

JavaScript 中遗留的糟粕太多。现在受到这些糟粕的影响,很多新的提案又不得不妥协。在未来,它会变得极其复杂。

也许某一天,会出现一个没有历史包袱的 JavaScript 子集来替换它。

今年输出的文章

最近两个月才开始写,希望能帮到大家,或者也可以加群一起学习进步。