【问题标题】:Replacing values in prototype: class static getters, or class fields?替换原型中的值:类静态 getter,还是类字段?
【发布时间】:2018-06-20 23:34:17
【问题描述】:

几年前,我编写了自己的“declare”实现来模仿 Dojo(有人吗?):https://github.com/mercmobily/simpleDeclare class 现在已经过时了。 SimpleDeclare 的美妙之处在于我可以这样做:

// Basic definition of the managers store
var Managers = declare( JsonRestStores, JsonRestStores.HTTPMixin, JsonRestStores.SimpleDbLayerMixin, {

  schema: new Schema({
    name   : { type: 'string', trim: 60 },
    surname: { type: 'string', searchable: true, trim: 60 },
  }),

  storeName: 'managers',
  publicURL: '/managers/:id',

  handlePut: true,
  handlePost: true,
  handleGet: true,
  handleGetQuery: true,
  handleDelete: true,
});
var managers = new Managers();

是的,它有多重继承;是的,handePut、handlePost 等东西被放置在“中间人”原型中。 必须将此代码转换为 ES6,我有两个选择: (我们暂时不讨论“mixins”...)

选项 1:静态 getter(最终将成为经理。***):

// Basic definition of the managers store
class Managers extends JsonRestStores {

  static get schema() { return new Schema({
    name   : { type: 'string', trim: 60 },
    surname: { type: 'string', searchable: true, trim: 60 },
  }),

  static get storeName() { return 'managers' }
  static get publicURL() { return '/managers/:id' }

  static get handlePut() { return true }
  static get handlePost() { return true }
  static get handleGet() { return true }
  static get handleGetQuery() { return true }
  static get handleDelete() { return true }
};
var managers = new Managers()

选项 2:落地时的类字段(在构造时将作为普通对象属性结束):

// Basic definition of the managers store
class Managers extends JsonRestStores {

  schema = new Schema({
    name   : { type: 'string', trim: 60 },
    surname: { type: 'string', searchable: true, trim: 60 },
  })

  storeName = 'managers'
  publicURL = '/managers/:id'

  handlePut = true
  handlePost = true
  handleGet = true
  handleGetQuery = true
  handleDelete = true
};
var managers = new Managers()

问题在于,这些解决方案都不像原型那样真正有效;在原型中拥有这些值给出了 1)默认值 2)实例找出父值是什么的能力(例如 manager.constructor.prototype)。 3) 实例更改这些值的能力(这有时很有用)

如果我使用static get,我会得到一些非常冗长的东西,好处是实例可以计算出父级的值,以及父级的父级;而且,除非我为每个设置器创建设置器,否则我也无法修改这些值

如果我使用类字段(甚至还不存在),我会得到更好的语法,主要的缺点是实例无法弄清楚早期的默认值是什么(因为所有值在实例中)

你会怎么做?

【问题讨论】:

  • 您应该使用类构造函数作为选项 2 的替代方案,您的属性最终仍将作为普通对象属性,但这适用于当前的 es6 类实现。
  • 类语法带有陷阱,处理多重继承尤其是一场噩梦。 Eric Elliot 的 posts 和 stampit library 在这个主题上非常有趣。
  • 你的意思是,在构造函数中的属性一一赋值?
  • re: 多重继承,我正在使用 Polymer 的模式来制作 mixins polymer-project.org/2.0/docs/devguide/… 虽然是的,但是多重继承更好:D
  • "现在 class 已经过时了" - 我不明白为什么。你的语法显然更合适。它确实有效。所以就留着吧!是什么让您认为您“必须将此代码转换为 ES6”?

标签: javascript ecmascript-6 es6-class ecmascript-next


【解决方案1】:

选项 1 会在每次访问属性时创建新的 Schema 实例,这是不可接受的开销,除非这是可取的行为。

选项 2 为每个 Managers 实例创建新的 Schema 实例。如果Managers 被子类化并且schema 被覆盖,Schema 将以任何方式实例化,这会提供开销。

如果所有Managers 实例都应该共享同一个schema 实例,则应将其分配给类原型:

Managers.prototype.schema = new Schema(...);

它也可以定义为静态属性,并且可以选择使用 getter 来加倍,以提供对类实例的更轻松访问。

在 ES.next 中:

class Managers extends JsonRestStores {
  static schema = new Schema(...);

  get schema() {
    return this.constructor.schema;
  }
  ...
}

在 ES6 中:

class Managers extends JsonRestStores {      
  get schema() {
    return this.constructor.schema;
  }
  ...
}

Managers.schema = new Schema(...);

【讨论】:

  • class Managers extends JsonRestStores { static schema = new Schema(...) 不是有效的 Javascript -- 我希望是
  • static 和 instance 类字段都是第 2 阶段提案。您在问题中使用了schema = ... 类字段并在其上放置了ecmascript-next 标记。如果您不使用 Babel 转译代码而是依赖本机实现,则类字段不适用,但不清楚您为什么要在问题中针对 ES.next 功能。 ES6 等价的静态类字段是Managers.schema = new Schema(...)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多