我正在阅读 John Resig 的《Javascript ninja secret 》,并正在尝试其中一个关于柯里化(Currying)和 parital 函数的示例。代码如下:
<html>
<body>
<button id="test">Click Me!</button>
</body>
<script type="text/javascript">
Function.prototype.curry = function() {
var fn = this,
args = Array.prototype.slice.call(arguments);
return function() {
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments)));
};
};
var elem = document.getElementById("test");
var bindClick = elem.addEventListener.curry("click");
bindClick(function(){ console.log("OK"); });
</script>
</html>
但是,以下代码似乎会生成错误 Uncaught TypeError: Illegal invoking on the apply function。
我似乎无法弄清楚原因,因为这一切似乎都有道理。
bindClick
将返回一个匿名函数,该函数以 window
作为函数上下文 (this
) 调用函数 elem.addEventListener
参数将是 ["click", function() {console.log("OK"); }]
最佳答案
问题是您丢失了元素的上下文。必须在元素上调用 addEventListener
方法,但您是在函数上调用它:
// Here, `this` refers to a function, not an element
return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));
您需要将元素传递给新函数。例如:
Function.prototype.curry = function () {
var fn = this,
args = Array.prototype.slice.call(arguments);
return function (context) {
return fn.apply(
context,
args.concat(Array.prototype.slice.call(arguments, 1))
);
};
};
这是一个working example 。请注意在返回的函数中添加了一个 context
参数,还要注意在 slice
调用中添加了第二个参数 - 这是删除新的 context 所必需的
参数,并且仅应用以下任何参数。
关于JavaScript 和柯里化(Currying),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15566519/