javascript 类型定义-JavaScript 的黑暗时刻?

最近,反正是双数的“#”字符,在后端圈子里燃起了熊熊大火。 熊熊燃烧的大火让很多使用 JavaScript 的开发者自责,他们的至暗时刻即将来临。

真正的原因是 ECMA TC39 委员会(技术委员会 39,简称 TC39)在 GitHub 上通过了一份关于 ECMAScript 语法特征的草案,即 JavaScript 中被称为弱类型语言的私有属性修饰符。类将是“#”字符。

示例如下:

class Counter extends HTMLElement {
  #x = 0;

  clicked() {
    this.#x++;
    window.requestAnimationFrame(this.render.bind(this));
  }

  constructor() {
    super();
    this.onclick = this.clicked.bind(this);
  }

  connectedCallback() { this.render(); }

  render() {
    this.textContent = this.#x.toString();
  }
}
window.customElements.define('num-counter', Counter);

事实上,我们都知道JavaScript中没有像Java和C++那样的private关键字来访问私有成员变量。 通常,开发人员通常使用“下划线_”作为私有成员变量约定的开头:

<code class="hljs javascript" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 3px;border-width: 1px 1px 1px 6px;border-style: solid;border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(33, 152, 99);color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">function Person(name){
this._name = name;
}

var person = new Person(‘Joe’);

或者利用JavaScript闭包的特性来模拟私有变量:

function Person(name){
var _name = name;
this.getName = function(){
return _name;
}
}

var person = new Person(‘Joe’);

由此javascript 类型定义,我们不禁要问,为什么不使用其他语言中一样的“private”来表示JavaScript类私有数组,而是使用“#”字符呢? 另外,“#”是Python、MySQL、R、Perl等编程语言中具有代表性的注释。 这会引起混乱吗?

为什么在 JavaScript 中不使用“private”而不是“#”?

开发者 Jamie 在文章“JavaScript 的新#private 类字段”() 中向我们解释了这一点。 上面提到,在Java、C++等编程语言中,private用来定义私有数组。 用法如下:

class EnterpriseFoo {
  public bar;
  private baz;
  method() {
    this.bar;
    this.baz;
  }
}

在这种语言中,公共和私有数组的访问方式相同。 因此,他们采用这些定义方法是合理的。

但在 JavaScript 中,由于我们无法使用 this.field 方法来访问私有属性,因此我们需要一种以句型的方式来传达关联性的方法。 通过在两个地方都使用符号#,可以很明显地看出正在引用哪个属性。

为什么引号需要“#”字符?

我们需要使用 this.#field 而不是 this.field 有几个原因:

为了封装,我们需要允许公共和私有数组具有相同的名称。 因此,访问私有数组不仅仅是普通的查找。

JavaScript 中的公共数组可以通过 this.field 或 this ['field'] 来引用。 私有数组很难支持第二种形式(因为它是静态的),这可能会导致混乱。

需要较高的检测“成本”。

让我们看一个代码示例:

class Point {
  #x;
  #y;

  constructor(x, y) {
    this.#x = x;
    this.#y = y;
  }
  equals(other) {
    return this.#x === other.#x && this.#y === other.#y;
  }
}

注意我们如何引用 other.#x 和 other.#y。 通过访问私有数组,我们假设 other 是 Point 类的实例。

因为我们已经使用了 # 符号语法,所以我们告诉 JavaScript 编译器我们正在从当前类中查找私有属性。

但是如果我们不使用#符号会发生什么呢?

equals(otherPoint) {
  return this.x === otherPoint.x && this.y === otherPoint.y;
}

现在我们遇到一个问题:我们怎么知道otherPoint是什么?

JavaScript 没有静态类型系统,因此 otherPoint 可以是任何东西。

这个问题主要有两个原因:

函数的行为取决于开发人员传递给它的值的类型:有时它访问私有属性,有时它查找公共属性。

我们每次都必须检查 otherPoint 的类型。

if (
  otherPoint instanceof Point &&
  isNotSubClass(otherPoint, Point)
) {
  return getPrivate(otherPoint, 'foo');
else {
  return otherPoint.foo;
}

更糟糕的是,我们必须对类中的每个属性访问执行此操作,以检测我们是否引用私有属性。

原始属性的获取已经很慢了,所以我们肯定不想降低它的权重。

因此,我们需要对私有属性使用#字符,因为使用其他方法会导致不可预测的行为和后果,升值可能会导致巨大的性能问题。

开发者心态

但尽管如此,草案刚刚通过,GitHub 上不少开发者还是坐不住了,纷纷站出来表示():

甚至有开发商对该提案进行了考察,结果显示出强烈反对:

与此同时,国外开发者也开启了吐槽模式:

基于此,TC39 委员会成员@littledan 回应说,我确实觉得 TC39 之外的社区观点很重要,并且希望在我们的决策中尽可能地考虑它。 我真的很想使用 GitHub 存储库作为沟通媒介来获得有关我们规范的更多反馈。 对于这项动议,我很抱歉没有给予更多的关注和更详细的初步审查。 我特别遗憾的是,当讨论出现消极心态时,我没有大力介入。 因为我想让开发者知道,您的意见对我和 TC39 的许多人来说非常重要。

除了 GitHub 上的讨论之外,我还在与各种库、框架的作者以及在更传统的面向对象编程语言方面拥有更多经验的开发人员进行交流。 对于其中许多人来说,缺乏易于使用的封装是 JavaScript 中的一个大漏洞,尽管普通开发人员需要一些时间来适应语法,但这些方法仍然被视为一种实用的选择。 我认为那些对该法案持积极态度的人不愿意对 GitHub 问题发表评论javascript 类型定义,这些问题更多的是表达异议。

鉴于世界上有数以百万计的 JavaScript 开发人员,开放流程很难在社区内达成绝对共识,但这并不意味着我们忽视此类意见。 但有时,我们必须做出艰难的选择,尽可能多地听取开发者社区的意见,而做出这样的选择是 TC39 有权做的事情。

您觉得这个新功能怎么样? 欢迎下方留言,分享你的想法。

微信已改版。

想要快速看到CSDN的热门文章,

赶紧把CSDN公众号设为明星吧。

打开公众号,点击“设为明星”即可!

征集论文”

CSDN公众号秉承“与千万技术人共同成长”的理念。 “技术头条”栏目深度解析行业热门技术和场景应用,让所有开发者紧跟技术趋势,保持警惕的技术意识,对行业趋势和技术有更全面的了解。

如果您有优质文章,或行业热点、技术趋势洞察,或深入应用实践、场景解决方案等新观点,请联系CSDN投稿。 联系方式:微信(guorui_1118,投稿请备注+姓名+公司职位)、邮箱(guorui@csdn.net)。