在 CoffeeScript 中重新实现 UnderscoreJS 链接
Reimplementing UnderscoreJS chaining in CoffeeScript
首先,
我阅读了关于此的 并觉得它们不适合我,因为我使用的是我继承的一系列方法,而不是一些我可以轻松更改的算术函数。其次,谷歌搜索 'javascript chaining method'
的结果主要与 jQuery 和 D3 有关。 JavaScript chain
方法的文档似乎少得令人惊讶。
我正在尝试 implement underscore 在 CoffeeScript 中。我正在研究 _.chain
方法。我正在将下划线方法装饰为 newObject
然后 returning 它。我有一个名为 value
的私有变量,它应该是被链式方法调用修改的值。在 returned newObject
上调用 getValue()
应该 return 私有 value
变量。
由于某些原因,当我在 newObject
上调用方法时,私有 value
变量没有改变。下划线方法被正确柯里化,但在调用函数时它们不会改变。我尝试阅读 underscore source code,但他们似乎以完全不同的方式构建了链式方法,如果不重构我的下划线对象的构造方式,我无法复制。
_.chain
_.chain = (v) ->
newObj = {}
value = v
newObj.getValue = -> value
for name, fn of _
if typeof fn is 'function'
newObj[name] = (callback, otherVal) ->
value = fn(value, callback, otherVal)
newObj
newObj
示例:
var a = _.chain([1,2,3,4]);
a.map(function(value) {
return value + 5;
})
a.getValue().getValue()
>>>[1, 2, 3, 4]
问题与闭包行为有关(毕竟这是 javascript)。问题出现在这里:
newObj[name] = (callback, otherVal) ->
value = fn(value, callback, otherVal)
newObj
fn
的值已关闭,只要在 newObj
上调用与 name
关联的函数时就会使用该值。问题在于 fn
的值在 chain
函数的整个生命周期中都会发生变化,因此关闭值也会发生变化。特别是,在 chain
退出后,您附加到 newObj
的每个下划线函数的闭包中 fn
的值将是 for name, fn of _
中最后迭代的任何函数环形。在这种情况下,该函数是 chain
,因此当您在示例中调用 map
时,当解释器命中行 value = fn(value, callback, otherVal)
时,fn
是 chain
函数。
这就是为什么您需要在您的示例中调用 getValue
两次:a.map(...)
在内部调用 chain
,因此它 returns 是一个链式对象。
为了解决这个问题,我们可以使用 IIFE,这样您附加到 newObj
的函数就不会关闭 fn
,而是关闭您想要的实际函数:
newObj[name] = ((f) ->
(callback, otherVal) ->
value = f(value, callback, otherVal)
newObj
)(fn)
现在,我们关闭 f
,而不是关闭 fn
供以后使用(以后,它不会是我们想要的 fn
)立即绑定为 fn
.
的 current 值
这是完整的固定版本,在 Coffeescript 中:
_.chain = (v) ->
newObj = {}
value = v
newObj.getValue = -> value
for name, fn of _
if typeof fn is 'function'
newObj[name] = ((f) ->
(callback, otherVal) ->
value = f(value, callback, otherVal)
newObj
)(fn)
newObj
你可以用你的例子检查它,看看它现在给出了正确的答案。
首先,
我阅读了关于此的 'javascript chaining method'
的结果主要与 jQuery 和 D3 有关。 JavaScript chain
方法的文档似乎少得令人惊讶。
我正在尝试 implement underscore 在 CoffeeScript 中。我正在研究 _.chain
方法。我正在将下划线方法装饰为 newObject
然后 returning 它。我有一个名为 value
的私有变量,它应该是被链式方法调用修改的值。在 returned newObject
上调用 getValue()
应该 return 私有 value
变量。
由于某些原因,当我在 newObject
上调用方法时,私有 value
变量没有改变。下划线方法被正确柯里化,但在调用函数时它们不会改变。我尝试阅读 underscore source code,但他们似乎以完全不同的方式构建了链式方法,如果不重构我的下划线对象的构造方式,我无法复制。
_.chain
_.chain = (v) ->
newObj = {}
value = v
newObj.getValue = -> value
for name, fn of _
if typeof fn is 'function'
newObj[name] = (callback, otherVal) ->
value = fn(value, callback, otherVal)
newObj
newObj
示例:
var a = _.chain([1,2,3,4]);
a.map(function(value) {
return value + 5;
})
a.getValue().getValue()
>>>[1, 2, 3, 4]
问题与闭包行为有关(毕竟这是 javascript)。问题出现在这里:
newObj[name] = (callback, otherVal) ->
value = fn(value, callback, otherVal)
newObj
fn
的值已关闭,只要在 newObj
上调用与 name
关联的函数时就会使用该值。问题在于 fn
的值在 chain
函数的整个生命周期中都会发生变化,因此关闭值也会发生变化。特别是,在 chain
退出后,您附加到 newObj
的每个下划线函数的闭包中 fn
的值将是 for name, fn of _
中最后迭代的任何函数环形。在这种情况下,该函数是 chain
,因此当您在示例中调用 map
时,当解释器命中行 value = fn(value, callback, otherVal)
时,fn
是 chain
函数。
这就是为什么您需要在您的示例中调用 getValue
两次:a.map(...)
在内部调用 chain
,因此它 returns 是一个链式对象。
为了解决这个问题,我们可以使用 IIFE,这样您附加到 newObj
的函数就不会关闭 fn
,而是关闭您想要的实际函数:
newObj[name] = ((f) ->
(callback, otherVal) ->
value = f(value, callback, otherVal)
newObj
)(fn)
现在,我们关闭 f
,而不是关闭 fn
供以后使用(以后,它不会是我们想要的 fn
)立即绑定为 fn
.
这是完整的固定版本,在 Coffeescript 中:
_.chain = (v) ->
newObj = {}
value = v
newObj.getValue = -> value
for name, fn of _
if typeof fn is 'function'
newObj[name] = ((f) ->
(callback, otherVal) ->
value = f(value, callback, otherVal)
newObj
)(fn)
newObj
你可以用你的例子检查它,看看它现在给出了正确的答案。