如果我有一个类,我将一些参数传递给:
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
如此优雅和紧凑!
答案 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'