问题
问题在于 Coffeescript 支持默认函数参数和解构赋值,但不能同时支持。允许更多代码重用和更复杂结构的最简单解决方案是让 coffeescript 进行解构,并自己承担处理默认参数的任务。幸运的是,这很容易,这要归功于 jQuery 的 extend(第一个解决方案)或该方法的 polyfills(第二个解决方案)。
jQuery 解决方案
我冒昧地稍微重写了您的代码,并且为了您的方便,我构建了一个有效的 JSFiddle:http://jsfiddle.net/scarl3tt/jkLjxyqe/
do ->
class UiDialog
_default =
url: 'secret'
data: 'something'
constructor: (options) ->
{@url, @data, @method} = $.extend({}, _default, options)
dlg1 = new UiDialog
data: null
method:'GET' # result arguments are { url: secret, data: null, method: 'GET' }
dlg2 = new UiDialog
url: 'myURL'
method: 'GET' # result arguments are { url: 'myURL', data: 'something', method: 'GET' }
$('body').append("<div><h1>dlg1</h1><pre>#{JSON.stringify dlg1}</pre>")
$('body').append("<div><h1>dlg2</h1><pre>#{JSON.stringify dlg2}</pre>")
return
原版JS解决方案
然而,承认 jQuery 不属于每个项目,一个好的解决方案是定义一个做同样事情的方法。我在第二个示例中提供了一个常见的extend polyfill 的咖啡脚本端口。这不是最有效的,但它很简洁:http://jsfiddle.net/scarl3tt/uq4tu6y1/
do (w=window) ->
utils = (w.utils = w.utils || {})
utils.extend = (target, others...) ->
for source in others
for name in Object.getOwnPropertyNames(source)
target[name] = source[name]
return target
class UiDialog
_default =
url: 'secret'
data: 'something'
constructor: (options) ->
{@url, @data, @method} = utils.extend({}, _default, options)
dlg1 = new UiDialog
data: null
method:'GET' # result arguments are { url: secret, data: null, method: 'GET' }
dlg2 = new UiDialog
url: 'myURL'
method: 'GET' # result arguments are { url: 'myURL', data: 'something', method: 'GET' }
$('body').append("<div><h1>dlg1</h1><pre>#{JSON.stringify dlg1}</pre>")
$('body').append("<div><h1>dlg2</h1><pre>#{JSON.stringify dlg2}</pre>")
return
请注意,我的 vanilla 解决方案确实包含并使用了 jQuery,但这仅仅是为了便于打印结果。实际上并不需要让它工作。
此外,为了清楚起见,我将 extend polyfill 放在 window.utils 命名空间中,而不是 window.$ 中。