I am reading through John Resig's Secrets of Javascript ninja and was trying out one of the examples on currying and parital functions. The code is as follows:

<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>

However, the following code seems to generate an error Uncaught TypeError: Illegal invocation on the apply function.

I cant seem to figure out the reason as it all seems to make sense. bindClick will return an anonymous function that calls the function elem.addEventListener with window as the function context (this) and the arguments will be ["click", function() {console.log("OK"); }]

有帮助吗?

解决方案

The problem is that you've lost the context of the element. The addEventListener method has to be called on an element, but you're calling it on a function:

// Here, `this` refers to a function, not an element
return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));

You would need to pass in the element to your new function. For example:

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))
         );
     }; 
};

Here's a working example. Notice the addition of a context argument to the returned function, and also notice the addition of the second argument to the slice call - that's needed to remove the new context argument and only apply any following arguments.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top