JavaScript的类字段声明(提案)

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

内容简介:要定义在单击时递增的计数器窗口组件,可以使用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的类字段声明(提案)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

The Shallows

The Shallows

Nicholas Carr / W. W. Norton & Company / 2011-6-6 / USD 15.95

"Is Google making us stupid?" When Nicholas Carr posed that question, in a celebrated Atlantic Monthly cover story, he tapped into a well of anxiety about how the Internet is changing us. He also crys......一起来看看 《The Shallows》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码

SHA 加密
SHA 加密

SHA 加密工具