2

我正在阅读 John Resig 的 Javascript ninja 的秘密,并尝试了其中一个关于 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 invocation on apply 函数。

我似乎无法弄清楚原因,因为这一切似乎都是有道理的。 将返回一个匿名函数,该函数使用函数上下文 ( )bindClick调用该函数,并且参数将是elem.addEventListenerwindowthis["click", function() {console.log("OK"); }]

4

1 回答 1

3

问题是您丢失了元素的上下文。该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))
         );
     }; 
};

这是一个工作示例。请注意向返回的函数添加了一个context参数,还请注意向slice调用添加了第二个参数 - 这是删除新context参数并仅应用任何后续参数所必需的。

于 2013-03-22T09:20:08.067 回答