如果我有一个类,我将许多参数传递给:
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'