您可以使用存在运算符:
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
使用对象(与其他选项相比,这导致 JS 非常少):Foo
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