Подтвердить что ты не робот

Деконструкция списка параметров в конструкторе класса - 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

Так элегантно и компактно!

4b9b3361

Ответ 1

Вы можете использовать экзистенциальный оператор:

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 и устанавливать их только как собственные свойства, если они входят в параметр 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

Ответ 2

Вы можете сделать это с помощью оператора ?=:

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

Если вы не возражаете переходить в позиционные аргументы, а не в хэш, вы также можете сделать это очень элегантно, используя значения параметров по умолчанию:

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

f = new Foo

Ответ 3

Вы можете определить объект по умолчанию и сделать что-то вроде этого.

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

Играйте с ним. Надеюсь, что это поможет.

Ответ 4

Существует более простой способ:

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

Ответ 5

Новая версия 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'