>科技>>正文

JavaScript 的黑暗时刻来了?

原标题:JavaScript 的黑暗时刻来了?

近日,横竖都是二的「#」字符在前端圈子点了一把熊熊烈火,燃烧起的浓烟让很多使用 Java 的开发者懊恼其黑暗时刻已来临。

这其中真实的原因是ECMA TC39 委员会(Technical Committee 39,简称TC39)在 GitHub 上通过了一条 ECMA 语法特性的草案,即被称之为弱类型语言的 Java 中,类的私有属性修饰符将以「#」字符来表示。

示例如下:

classCounterextendsHTMLElement{

#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);

事实上,我们都知道在 Java 中并没有像 Java 和 C++ 中的 private 关键字来访问私有成员变量,通常开发者更多的是采取以“下划线_”为开头将变量约定为私有成员:

functionPerson(name){

this._name = name;

}

varperson = newPerson(‘Joe’);

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

functionPerson(name){

var_name = name;

this.getName = function(){

return_name;

}

}

varperson = newPerson(‘Joe’);

由此,我们不禁产生疑问,为何不用和其他语言相同的“private”来表示Java 类私有字段,而是“#”字符?况且“#”在 Python、MySQL、R、Perl 等编程语言中都是代表的注释,这样是否会造成混乱?

Java 中为何不用“private”替代“#”?

对此,开发者 Jamie 在《Java's new #private class fields》(https://jamie.build/javas-new-private-class-fields.html)一文中为我们做了解释,也正如上文所述,在 Java、C++ 等编程语言中,都会使用 private 来定义私有字段,用法如下:

classEnterpriseFoo{

publicbar;

privatebaz;

method() {

this.bar;

this.baz;

}

}

在这些语言中,公有和私有字段的访问方式相同。因此,它们采用这种定义方式也是合理的。

但是在 Java 中,因为我们不能使用 this.field 的方式去访问私有属性,那么我们就需要一种在语法上传达关联的方法。通过在这两个地方都使用符号 #,到底在引用哪个属性就很明显了

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

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

  1. 为了封装性,我们需要允许公有和私有字段可以同时具有相同的名称。因此,访问一个私有字段不仅仅是普通的查找。
  2. Java 中的公有字段可以通过 this.field 或 this ['field'] 引用。而私有字段将无法支持第二种语法方式(因为它是静态的),这可能会导致混淆。
  3. 需要昂贵的检查“代价”。

来看一个代码示例:

classPoint{

#x;

#y;

constructor(x, y) {

this.#x = x;

this.#y = y;

}

equals(other) {

returnthis.#x === other.#x && this.#y === other.#y;

}

}

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

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

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

equals(otherPoint) {

returnthis.x === otherPoint.x && this.y === otherPoint.y;

}

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

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

这是一个问题主要出于两个原因:

  1. 函数的行为取决于开发者传递给它的值的类型:有时访问私有属性,有时查找公有属性。
  2. 我们必须每次都检查 otherPoint 的类型。

if(

otherPoint instanceof Point &&

isNotSubClass(otherPoint, Point)

) {

returngetPrivate(otherPoint, 'foo');

} else{

returnotherPoint.foo;

}

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

本来属性的访问已经非常慢了,所以我们绝对不想再增加它的权重。

因此,我们需要对私有属性使用 # 字符,因为使用其他方式会造成不可预料的行为和后果,升值可能带来巨大的性能问题。

开发者的态度

但即使如此,草案刚刚通过,GitHub 上的不少开发者还是坐不住了,纷纷站出来表示(https://github.com/tc39/proposal-class-fields/pull/140):

  • 这个字符对我而言,看起来真的容易混乱。在社区中的开发者频频说不的同时,TC39 竟对这个草案达成共识?!对此,我真的很失望。我不想说这是自 ES4 发展历史以来最黑暗的一天,因为历史会证明一切。
  • TC39 委员会内部可能达成共识(尽管我知晓至少有一位委员会成员不同意这一点),但 TC39 和社区之间肯定没有达成共识,我不明白他们为何会忽略这一点。
  • 我更宁愿“private”而不是“#”作为 Java 私有属性的修饰符。作为 @ 装饰器的语法,也许“#”未来会被用于另一种特殊的语法。

甚至有开发者针对提案做了调研,结果显示反对声很强烈:

同时国内的开发者也开启了吐槽模式:

基于此,TC39 委员会成员@littledan 回应表示,我真的认为 TC39 之外的社区观点非常重要,并希望在我们的决策中尽可能地考虑它。我真的想通过 GitHub repos 作为通信媒介,以获得针对我们的规范更多的反馈意见。针对这个提案,我很抱歉没有更详细地关注和审核。尤其令我感到遗憾的是,当讨论有负面态度时,我没有强烈的干预。因为我想让开发者都知道你的意见对我和 TC39 中的许多人都非常重要。

除了在 GitHub 的讨论之外,我也一直在与各种库、框架的作者以及在更传统的面向对象编程语言方面有更多经验的开发者交谈。对于这些人中的许多人来说,缺乏易于使用的封装是 Java 中的一个大漏洞,虽然通常开发者需要一些时间来习惯语法,但这种方法仍被视为一种实用的选择。我觉得那些对这个提案持肯定态度的人不太愿意在 GitHub 问题上发表评论,而这些问题更多的是表达不同意见。

鉴于世界上数以百万计的 Java 开发者,开放流程无法在整个社区中达成绝对的共识,但这并不意味着我们会忽略这些意见。但有时候,我们必须做出艰难的选择,尽可能多地考虑社区开发者的意见,并做出这些选择是 TC39 有权做的事情。

你如何看待这项新特性?欢迎下方留言,分享你的看法。

征稿啦

返回搜狐,查看更多

责任编辑:

声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
阅读 ()
投诉
免费获取
今日推荐