Javascript 使用字符串数组创建嵌套函数的对象以形成对象键
我使用以下构造作为模拟对象,其功能类似于具有可链接方法的对象:Javascript 使用字符串数组创建嵌套函数的对象以形成对象键,javascript,coffeescript,method-chaining,Javascript,Coffeescript,Method Chaining,我使用以下构造作为模拟对象,其功能类似于具有可链接方法的对象: PlayerNull = find : -> populate : -> exec : (callback) -> callback false, false 在我的测试中,我用真实模型替换这个模拟对象,我的控制器依次调用每个函数,例如: Model.find().populate().exec(callback) 由于我发现自己多次使用这个函数,我很好奇是否可以创建一个
PlayerNull =
find : ->
populate : ->
exec : (callback) ->
callback false, false
在我的测试中,我用真实模型替换这个模拟对象,我的控制器依次调用每个函数,例如:
Model.find().populate().exec(callback)
由于我发现自己多次使用这个函数,我很好奇是否可以创建一个助手函数来简化它(稍微),使用以下形式的助手函数:
PlayerNull = helper.mockNest ['find', 'populate', 'exec'], (callback) ->
callback false, false
我看到了以下函数代码,但这不起作用:
exports.mockNest = (func_names, func_final) ->
func_names.reverse()
func_next = func_final
for func_name in func_names
_func_next = func_next.bind({})
_next = {}
_next[func_name] = ->
_func_next
func_next = _func_next
func_next
我意识到我需要克隆
func_next
每个循环,否则引用似乎会被维护,而分配给func_next
似乎会改变以前的所有分配。是的,您已经正确地确定了问题,即引用没有被维护,这是经典问题
然而,克隆函数在这里并没有真正的帮助,您的实际问题是
它在\u func\u next
变量上创建一个闭包,该变量在每次循环迭代中都会修改
应该是这样
exports.mockNest = (func_names, func_final) ->
func_names.reverse()
func_next = func_final
for func_name in func_names
next = {}
next[func_name] = func_next
func_next = do (_next = next) ->
() ->
_next
func_next
多亏了Bergi的解释,我得出了以下解决方案:
exports.mockNest = (func_names, func_final) ->
# Assign the last function to the provided func_final
func_name_final = func_names.pop()
func_next = {}
func_next[func_name_final] = func_final
# Reverse the array so we build the object from last to first.
func_names.reverse()
for func_name in func_names
ignore = do (func_name, _func_next = func_next) ->
func_next = {}
func_next[func_name] = ->
_func_next
return
func_next
为了解释这些更改,我需要保留提供的func_final,因此我必须在循环之前赋值
此外,我还需要将
do
块分配给变量ignore
,否则Coffeescript会将函数编译到不同的位置,其中对func\u next
所做的更改是无序的。分配确保了do
块的位置。非常感谢您解释问题并让我注意到do
关键字,非常酷,让我越过了终点线。你的最终代码没有完全工作,我将添加一个答案并接受它;但解决办法相当小。与您的代码相比,它甚至可以使用空的func\u names
数组。
exports.mockNest = (func_names, func_final) ->
# Assign the last function to the provided func_final
func_name_final = func_names.pop()
func_next = {}
func_next[func_name_final] = func_final
# Reverse the array so we build the object from last to first.
func_names.reverse()
for func_name in func_names
ignore = do (func_name, _func_next = func_next) ->
func_next = {}
func_next[func_name] = ->
_func_next
return
func_next