【发布时间】:2013-06-27 21:46:38
【问题描述】:
在 JavaScript 中,为函数定义部分应用方法非常容易:
Function.prototype.partial = function partial() {
var fn = this
var args = Array.prototype.slice.call(arguments)
return function() {
var newArgs = Array.prototype.slice.call(arguments)
return fn.apply(this, args.concat(newArgs))
}
}
它适用于函数:
var biggerThanFive = Math.max.partial(5)
assert biggerThanFive(x) === Math.max(5, x)
但结果函数的“this”与原始函数不同:
function Test() {
this.name = 'test'
}
Test.prototype.a = function(b) {
return [this.name, b]
}
var test = new Test()
test.a('x') // ['test','x']
var b = test.a.partial('y')
b() // [undefined,'y']
这可以通过手动将生成的函数绑定回其原始绑定对象来解决:
var c = test.a.partial('z').bind(test)
c() //['test','z']
如何在Function.prototype.partial 定义中执行此操作? test.a 客观地知道它的“this”是“测试”,那么我该如何获取这些知识呢?
我从 Esailija 那里学到了什么:
JavaScript 不会在调用时以外的任何时候确定函数内部的“this”是什么。 var d = [].concat 与 var d = Array.prototype.concat 没有什么不同,调用 d() 将在全局对象上调用它,因为“它的左侧”没有任何内容。
【问题讨论】:
-
这是
this关键字的问题,而不是您编写的“部分应用程序”方法。调用b()时this的值将是全局范围(即几乎所有浏览器中的window),如果没有名为name的全局变量,那么您将得到undefined背部。对于浏览器而言,test.a与b的关系并不明显,因为它仅作为具有匿名函数的变量出现在解释器中。 -
是的,我知道,这就是我想要规避的 :) bind 可以做到,但我想在部分方法中做到这一点。
标签: javascript functional-programming partials