JavaScript的类字段声明(提案)

栏目: JavaScript · 发布时间: 4年前

内容简介:要定义在单击时递增的计数器窗口组件,可以使用ES2015定义以下内容:使用ESnext字段声明提议,上面的示例可以写成:在上面的示例中,您可以看到使用语法x = 0声明的字段。您还可以将没有初始值设定项的字段声明为x。

要定义在单击时递增的计数器窗口组件,可以使用ES2015定义以下内容:

class Counter extends HTMLElement {
  clicked() {
    this.x++;
    window.requestAnimationFrame(this.render.bind(this));
  }

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

  connectedCallback() { this.render(); }

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

2. 预先声明属性

使用ESnext字段声明提议,上面的示例可以写成:

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);
复制代码

在上面的示例中,您可以看到使用语法x = 0声明的字段。您还可以将没有初始值设定项的字段声明为x。

  • 通过预先声明字段,类定义变得更加自我文档化;
  • 实例经历较少的状态转换,因为声明的字段始终存在。

私有属性

下面的示例有一些实现细节,属性可以更好地保留在内部。 使用ESnext私有字段和方法,可以将定义细化为:

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);
复制代码

要使字段私有,只需给它们一个以#开头的名称。

通过定义在类外部不可见的内容,ESnext提供了更强大的封装,确保您的类的用户不会因为依赖于内部而产生意外。

请注意,ESnext仅在字段声明中提供预先声明的私有字段,正常属性的方式不能创建。

主要设计要点

使用Object.defineProperty创建的公有属性

公有属性声明使用Object.defineProperty(我们在TC39术语中将[[Define]]语义引用)定义实例上的字段,而不是使用this.field = value; (称为[[Set]]语义)。 以下是影响的示例:

class A {
  set x(value) { console.log(value); }
}
class B extends A {
  x = 1;
}
复制代码

使用所采用的语义,new B()将导致一个对象具有值为1的属性x,并且不会将任何内容写入控制台。 使用备用[[Set]]语义,1将被写入控制台,并且尝试访问该属性将导致TypeError(因为缺少getter)。

在[[Set]]和[[Define]]之间进行选择是一种设计决策,它对比了不同类型的行为预期:预期字段将作为数据属性创建,而不管超类包含什么;预期setter将被调用。经过长时间的讨论,TC39确定了[[Define]]语义,发现保持第一个期望很重要。

基于Object.defineProperty的公共字段语义的决定是基于TC39内部的广泛讨论和与开发人员社区的协商。不幸的是,社区相当分裂,而TC39则强烈支持Object.defineProperty。

作为一种缓解,decorators建议提供了编写decorator的工具,使公共字段声明使用[[Set]]语义。即使您不同意默认值,也可以使用其他选项。(无论TC39选择哪种缺省值,都是这种情况。)

公共字段在Chrome 72中带有[[Define]]语义,这个语义决定不太可能被重新访问。

没有初始化项的字段被设置为undefined

无论是否存在初始化,公共字段声明和私有字段声明都会在实例中创建一个字段。如果没有初始化器,则将字段设置为undefined。这与某些转置器实现稍有不同,后者将完全忽略没有初始化器的字段声明。

例如,在下面的示例中,new D将生成一个对象,其y属性未定义,而不是1。

class C {
  y = 1;
}
class D extends C {
  y;
}
复制代码

将没有初始化项的字段设置为undefined(而不是擦除它们)的语义是,字段声明提供了可靠的基础,以确保在创建的对象上呈现属性。这有助于 程序员 将对象保持在相同的一般状态,这可以很容易地进行推理,有时在实现中更易于优化。

私有语法

私有字段基于使用#的语法,在声明字段和访问字段时都使用#。

class X {
  #foo;
  method() {
    console.log(this.#foo)
  }
}
复制代码

这种语法试图既简洁又直观,尽管它与其他编程语言有很大的不同。 没有私有的计算属性名:#foo是一个私有标识符,#[foo]是一个语法错误。

没有后门访问私有属性

私有字段提供了一个强大的封装边界:从类外部访问私有字段是不可能的,除非有一些显式代码来公开它(例如,提供getter)。这与JavaScript属性不同,JavaScript属性支持各种反射和元编程,而类似于闭包和WeakMap等机制,这些机制不提供对其内部的访问。

执行初始化

在构造函数运行时,公共字段和私有字段都按声明的顺序添加到实例中。初始化器将为每个类实例重新计算。字段在初始化器运行后立即添加到实例中,然后再计算下面的初始化器。

作用域:作为初始化器表达式中的这个值,正在构造的实例位于作用域中。新的。目标未定义,如在方法中。对参数的引用是早期的错误。超方法调用Super .method()在初始化器中可用,但是超构造函数调用Super()是一个语法错误。即使类在异步函数/genenerator中声明,初始化器中也不能使用wait和yield。

当计算字段初始化器并将字段添加到实例时:

  • 基类:在构造函数执行的开始,甚至在参数析构之前。
  • 派生类:就在super()返回之后。(调用super()的灵活性导致许多实现为这种情况创建了一个单独的不可见initialize()方法。)

如果派生类中没有调用super(),并且没有将其他一些公共和私有字段添加到实例中,也没有计算初始化器。对于基类,初始化器总是被求值,即使构造函数最终返回其他东西。new.initialize proposal将添加一种方法,以编程方式向一个实例添加字段,而该实例不是来自基类中的super()/这个值。


以上所述就是小编给大家介绍的《JavaScript的类字段声明(提案)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

《电脑报》2005年合订本(上下)

《电脑报》2005年合订本(上下)

电脑报社主编 / 西南师范大学出版社 / 2006-1 / 45.00元

全套上、下两册,浓缩2005年电脑报精华文章;附录包含70余篇简明IT应用指南,涵盖软件、硬件、数码、网络四大领域,配赠权威实用的2005-2006中国计算机年鉴光盘,近1.4GB海量信息与资源超值奉献,提供2005-2006全系列硬件、数码产品资讯,兼具知识性与资料性,连结购买每年《电脑报合订本》,你将拥有一套完整的实用大型电脑文库。一起来看看 《《电脑报》2005年合订本(上下)》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具