解构类构造函数中的参数列表 - 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;

在咖啡中是:

@bar = parameters.bar ? 10

如此优雅紧凑!

您可以使用存在运算符:

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

另一种方法是直接extend Foo对象,如果您相信将传递的唯一选项是有效的选项(与其他选项相比,这会导致 JS 非常少(:

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

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

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

您可以使用

?=运算符执行此操作:

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

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

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

您可以定义一个默认值对象并执行以下操作。

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

玩它。希望有帮助。

有一个更简单的方法:

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

新版本的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'

最新更新