解构类构造函数中的参数列表 - Coffeescript

时间:2012-07-15 15:29:15

标签: coffeescript

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

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;

并且在coffescript中是:

@bar = parameters.bar ? 10

如此优雅和紧凑!

5 个答案:

答案 0 :(得分:29)

您可以使用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

如果你没有使用下划线,还有$.extend(谁还不使用jQuery?):

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

另一种选择是直接extend Foo class Foo defaults = bar: 10, moo: 20 constructor: (options = {}) -> $.extend @, defaults, options 对象,如果您相信将传递的唯一选项是有效选项(与其他选项相比,这导致JS非常小):< / p>

Foo.prototype

最后一种方法是在class Foo bar: 10 moo: 20 constructor: ({bar, moo} = {}) -> @bar = bar if bar? @moo = moo if moo? 中设置默认值,如果它们出现在options参数中,则只将它们设置为自己的属性:

Foo

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

正如您所看到的,有很多方法可以做到这一点。它们都不是完美的,它们都有它们的优点和缺点,所以尽量选择一个更适合你的需求/品味/无论什么= D

答案 1 :(得分:3)

您可以使用?=运算符执行此操作:

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

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

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

f = new Foo

答案 2 :(得分:2)

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

 (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;      
})();

玩它。希望有所帮助。

答案 3 :(得分:1)

有一种更简单的方法:

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

答案 4 :(得分: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'