你可以使用
存在运算符:
class Foo
constructor: (options = {}) ->
@bar = options.bar ? 10
@moo = options.moo ? 20
那个构造函数编译为:
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代码中,传递带有选项的对象是一种常见模式,因此一些库提供了有用的实用函数来帮助处理这个问题。例如,Underscore提供了_.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
另一种方法是直接扩展
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