覆盖咖啡脚本类和子类中的变量

时间:2017-12-08 20:28:06

标签: inheritance coffeescript default

我是一名试图创建一个小型JavaScript库的Ruby程序员。

由于我不是一位杰出的JavaScript专家,因此我在使用CoffeeScript帮助自己,在一个相当不为人知的领域中奋战。

这个想法:

我想创建几个小的JavaScript小部件,所有小部件都共享一些小功能。

共享功能和配置位于Base类中。每个小部件都有自己的类,它继承自Base,可以设置自己的配置(甚至覆盖Base的配置。)

最后,当实例化窗口小部件时,可以传递一个选项哈希,它本身会覆盖窗口小部件的默认选项。

到目前为止看起来像这样:

@Adg = {}

class Adg.Base
  config =
    debugMessage:   false
    hiddenCssClass: 'visually-hidden'

  # Constructor. Should not be overridden; use @init() instead.
  #
  # - Arg1: The DOM element on which the script should be applied (will be saved as @$el)
  # - Arg2: An optional hash of options which will be merged into the global default config
  constructor: (el, options = {}) ->
    @config = config

    @$el = $(el)

    for key, val of options
      @config[key] = val

    @init()

  # Dummy, must be overridden in inheriting classes.
  init: ->
    throw 'Classes extending App must implement method init()!'

class Adg.Autocomplete extends Adg.Base
  config =
    suggestionsContainer: 'fieldset'
    suggestionsContainerLabel: 'legend'
    alertsContainerId: 'alerts'

  init: ->
    # Merge config into existing one
    for key, val of config
      @config[key] = val

这有效,但对我来说却很笨拙:

  • 我不喜欢我必须创建默认constructor,不能通过继承类来覆盖(我添加init()方法作为替代)
  • 在每个继承类中,我必须手动合并配置

1 个答案:

答案 0 :(得分:1)

我相信以下内容可以满足您的需求:

@Adg = {}

class Adg.Base

  @config =
    debugMessage:   false
    hiddenCssClass: 'visually-hidden'

  constructor: (el, options = {}) ->
    @config = Object.assign {}, Adg.Base.config, options
    @$el = $(el)

class Adg.Autocomplete extends Adg.Base

  @config =
    suggestionsContainer: 'fieldset'
    suggestionsContainerLabel: 'legend'
    alertsContainerId: 'alerts'

  constructor: (el, options={}) ->
    super(el, Object.assign({}, options, Adg.Autocomplete.config))

我做了一些改变:

  1. 使用类属性而不是局部变量/闭包。 @config上的Adg.Base使用Adg.Base.config
  2. 阅读
  3. 使用super从子项中调用父构造函数。
  4. 使用Object.assign合并哈希值。
  5. 请注意,如果您正在使用Coffeescript 2(卸载coffee-script并安装coffeescript @ next软件包),则可以使用spread运算符而不是Object.assign:

    @config = {Adg.Base.config..., config...}`