【问题标题】:Deconstructing a list of parameters in class constructor - Coffeescript在类构造函数中解构参数列表 - Coffeescript
【发布时间】:2012-07-14 15:25:39
【问题描述】:

如果我有一个类,我将许多参数传递给:

class Foo

  constructor: (parameters) ->

  @bar = parameters.bar
  @moo = parameters.moo

类是这样创建的:

foo = new Foo(bar: 2, moo: 8)

我的问题是在构造函数中检测传递的变量是否存在以及不设置默认值的最优雅方法是什么。我会在 javascript 中这样做的方式是:

this.bar = ( parameters.bar !== undefined ) ? parameters.bar : 10;

其中 10 是默认值。

感谢您的帮助:)

好的答案 - 只是总结最好的:

为了检测参数是否存在,如果不存在则定义一个默认值,在javascript中是:

this.bar = ( parameters.bar !== undefined ) ? parameters.bar : 10;

在咖啡脚本中是:

@bar = parameters.bar ? 10

如此优雅和紧凑!

【问题讨论】:

标签: coffeescript


【解决方案1】:

新版本的coffeescript有一个很好的方法来解决这个确切的问题

class MyObject
  constructor: ({string1='x', string2='y'} = {})

它也适用于常规函数

myFunction = ({string1='x', string2='y'} = {}) ->
  string1 + string2

console.log myFunction({string1:"a", string2:"b"}) 
# outputs: 'ab'

console.log myFunction() 
# outputs: 'xy'

【讨论】:

    【解决方案2】:

    还有一种更简单的方法:

    class Foo
      constructor: (parameters = {}) ->
        {
          @bar = 10
          @moo = 20
        } = parameters
    

    【讨论】:

      【解决方案3】:

      您可以使用existential operator:

      class Foo
        constructor: (options = {}) ->
          @bar = options.bar ? 10
          @moo = options.moo ? 20
      

      该构造函数编译为:

      // Compiled JS.
      function Foo(options) {
        var _ref, _ref1;
        if (options == null) {
          options = {};
        }
        this.bar = (_ref = options.bar) != null ? _ref : 10;
        this.moo = (_ref1 = options.moo) != null ? _ref1 : 20;
      }
      

      一种等效的替代方法是立即销毁选项对象(因此避免不必要的名称),然后设置默认值以防这些选项未通过:

      class Foo
        constructor: ({@bar, @moo} = {}) ->
          @bar ?= 10
          @moo ?= 20
      

      由于传递带有选项的对象是 JS 代码中的一种常见模式,因此一些库具有有用的实用程序函数可以帮助解决此问题。例如,下划线提供_.defaults,我认为这会产生非常可读的代码:

      class Foo
        constructor: ({@bar, @moo} = {}) ->
          _.defaults @, bar: 10, moo: 20
      

      如果不使用Underscore,还有$.extend(反正谁不用jQuery?):

      class Foo
        defaults = bar: 10, moo: 20
        constructor: (options = {}) ->
          {@bar, @moo} = $.extend {}, defaults, options
      

      如果您相信将传递的唯一选项是有效选项(与其他选项相比,这导致 JS 非常少),则可以直接替换 extend Foo 对象:

      class Foo
        defaults = bar: 10, moo: 20
        constructor: (options = {}) ->
          $.extend @, defaults, options
      

      最后一种选择是在Foo.prototype 中使用默认值,并且仅当它们出现在 options 参数中时才将它们设置为自己的属性:

      class Foo
        bar: 10
        moo: 20
        constructor: ({bar, moo} = {}) ->
          @bar = bar if bar?
          @moo = moo if moo?
      

      这可以防止Foo 的所有实例拥有自己的单独属性,而是在它们使用默认值时在实例之间共享相同的属性,这与通常对方法所做的相同。您也可以通过@bar = bar if @bar isnt bar 仅在参数值与默认值不同时分配这些属性。

      如您所见,有很多方法可以做到这一点。它们都不是完美的,它们都有其优点和缺点,因此请尝试选择更适合您的需求/口味/随便的一种=D

      【讨论】:

      • 这么多好的答案,但最优雅的是:@bar = options.bar ? 10
      • 真的很喜欢那里的$.extend @, defaults, options 方法。
      【解决方案4】:

      您可以定义一个默认对象并执行类似的操作..

       (parameters = {}) ->
         this[key] = parameters[key] ? defaults[key] for key, value of defaults
      

      但你真的不必经历所有这些。创建默认值的最简单方法就是使用原型继承...

      class Foo
        bar: 10
        moo: 10
        constructor: (parameters = {}) ->
          this[key] = value for own key, value of parameters
      

      假设以上:

      a = new Foo();
      a.bar # => 10
      b = new Foo(bar: 50)
      b.bar # => 50
      

      除了构造函数之外,您使用 : 定义的每个属性都将成为对象原型上的属性。

      类定义转换为这个 JavaScript:

      Foo = (function() {      
        Foo.prototype.bar = 10;      
        Foo.prototype.moo = 10;
        //etcetc
        return Foo;      
      })();
      

      玩它。希望对您有所帮助。

      【讨论】:

        【解决方案5】:

        您可以使用?= 运算符来做到这一点:

        class Foo
          constructor: (parameters) ->
           @bar = parameters.bar
           @bar ?= 10
           @moo = parameters.moo
           @moo ?= 20
        

        如果您不介意传入位置参数而不是哈希,您也可以使用默认参数值非常优雅地执行此操作:

        class Foo
          constructor: (@bar = 10, @moo = 20) ->
        
        f = new Foo
        

        【讨论】:

          猜你喜欢
          • 2012-09-29
          • 1970-01-01
          • 2017-04-01
          • 2021-03-12
          • 2021-03-18
          • 2013-03-16
          • 2011-09-25
          • 1970-01-01
          • 2021-09-23
          相关资源
          最近更新 更多